网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等 *** 作都是通过该Socket实现的。
下面用Socket实现一个windows下的c语言socket通信例子,这里我们客户端传递一个字符串,服务器端进行接收。
【服务器端】#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>
#include <winsock2.h>
#define SERVER_PORT 5208 //侦听端口
void main()
{
WORD wVersionRequested
WSADATA wsaData
int ret, nLeft, length
SOCKET sListen, sServer //侦听套接字,连接套接字
struct sockaddr_in saServer, saClient //地址信息
char *ptr//用于遍历信息的指针
//WinSock初始化
wVersionRequested=MAKEWORD(2, 2) //希望使用的WinSock DLL 的版本
ret=WSAStartup(wVersionRequested, &wsaData)
if(ret!=0)
{
printf("WSAStartup() failed!\n")
return
}
//创建Socket,使用TCP协议
sListen=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
if (sListen == INVALID_SOCKET)
{
WSACleanup()
printf("socket() faild!\n")
return
}
//构建本地地址信息
saServer.sin_family = AF_INET //地址家族
saServer.sin_port = htons(SERVER_PORT) //注意转化为网络字节序
saServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY) //使用INADDR_ANY 指示任意地址
//绑定
ret = bind(sListen, (struct sockaddr *)&saServer, sizeof(saServer))
if (ret == SOCKET_ERROR)
{
printf("bind() faild! code:%d\n", WSAGetLastError())
closesocket(sListen) //关闭套接字
WSACleanup()
return
}
//侦听连接请求
ret = listen(sListen, 5)
if (ret == SOCKET_ERROR)
{
printf("listen() faild! code:%d\n", WSAGetLastError())
closesocket(sListen) //关闭套接字
return
}
printf("Waiting for client connecting!\n")
printf("Tips: Ctrl+c to quit!\n")
//阻塞等待接受客户端连接
while(1)//循环监听客户端,永远不停止,所以,在本项目中,我们没有心跳包。
{
length = sizeof(saClient)
sServer = accept(sListen, (struct sockaddr *)&saClient, &length)
if (sServer == INVALID_SOCKET)
{
printf("accept() faild! code:%d\n", WSAGetLastError())
closesocket(sListen) //关闭套接字
WSACleanup()
return
}
char receiveMessage[5000]
nLeft = sizeof(receiveMessage)
ptr = (char *)&receiveMessage
while(nLeft>0)
{
//接收数据
ret = recv(sServer, ptr, 5000, 0)
if (ret == SOCKET_ERROR)
{
printf("recv() failed!\n")
return
}
if (ret == 0) //客户端已经关闭连接
{
printf("Client has closed the connection\n")
break
}
nLeft -= ret
ptr += ret
}
printf("receive message:%s\n", receiveMessage)//打印我们接收到的消息。
}
// closesocket(sListen)
// closesocket(sServer)
// WSACleanup()
}
【客户端】
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#define SERVER_PORT 5208 //侦听端口
void main()
{
WORD wVersionRequested
WSADATA wsaData
int ret
SOCKET sClient //连接套接字
struct sockaddr_in saServer //地址信息
char *ptr
BOOL fSuccess = TRUE
//WinSock初始化
wVersionRequested = MAKEWORD(2, 2) //希望使用的WinSock DLL的版本
ret = WSAStartup(wVersionRequested, &wsaData)
if(ret!=0)
{
printf("WSAStartup() failed!\n")
return
}
//确认WinSock DLL支持版本2.2
if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)
{
WSACleanup()
printf("Invalid WinSock version!\n")
return
}
//创建Socket,使用TCP协议
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
if (sClient == INVALID_SOCKET)
{
WSACleanup()
printf("socket() failed!\n")
return
}
//构建服务器地址信息
saServer.sin_family = AF_INET //地址家族
saServer.sin_port = htons(SERVER_PORT) //注意转化为网络节序
saServer.sin_addr.S_un.S_addr = inet_addr("192.168.1.127")
//连接服务器
ret = connect(sClient, (struct sockaddr *)&saServer, sizeof(saServer))
if (ret == SOCKET_ERROR)
{
printf("connect() failed!\n")
closesocket(sClient) //关闭套接字
WSACleanup()
return
}
char sendMessage[]="hello this is client message!"
ret = send (sClient, (char *)&sendMessage, sizeof(sendMessage), 0)
if (ret == SOCKET_ERROR)
{
printf("send() failed!\n")
}
else
printf("client info has been sent!")
closesocket(sClient) //关闭套接字
WSACleanup()
}
请终端下输入sudo netstat -a
如果看到了,如果能看到很多unix的链接流。则证明linux系统本身已经启用了很多socket通信。已经是设置好的。
至于如何进行socket通信编程。请寻找相关资料自学。
如果你只是想建立到远端服务器的一个ip隧道。架设加密代理的隧道,那么请告知你使用的linux版本,以及使用的软件。
Socket通信创建步骤:
(1)通过socket()函数创建socket
(2)通过bind函数绑定socket于设备地址
(3)进行读写 *** 作read/recv/recvfrom write/send/sendto
(4)close方法关闭套接字
例子如下:
test1.c
#include <stdio.h>#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(void)
{
//create socket
int fd = socket(AF_INET, SOCK_DGRAM, 0)
if(fd==-1)
{
perror("socket\n")
exit(-1)
}
printf("socket fd=%d\n",fd)
//build connection address
struct sockaddr_in addr
addr.sin_family = AF_INET
addr.sin_port = htons(6666)
addr.sin_addr.s_addr = inet_addr("127.0.0.1")
int r
r = bind(fd,(struct sockaddr*)&addr,sizeof(addr))
if(r==-1)
{
perror("bind")
close(fd)
exit(-1)
}
printf("bind address successful!\n")
//accept or send message
char buf[255]
struct sockaddr_in from
socklen_t len
len = sizeof(from)
while(1)
{
r = recvfrom(fd,buf,sizeof(buf)-1,0,(struct sockaddr*)&from,&len)
if(r>0)
{
buf[r]=0
printf("The message from %s is:%s\n",inet_ntoa(from.sin_addr),buf)
}
else
{
break
}
}
//close socket
close(fd)
return 0
}
test2.c
#include <stdio.h>#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(void)
{
//create socket
int fd = socket(AF_INET,SOCK_DGRAM,0)
if(fd==-1)
{
perror("socket")
exit(-1)
}
printf("create socket OK!\n")
//create an send address
struct sockaddr_in addr={}
addr.sin_family = AF_INET
addr.sin_port = htons(6666)
addr.sin_addr.s_addr=inet_addr("127.0.0.1")
//send the message to the specify address
int r
char buf[255]
while(1)
{
r = read(0,buf,sizeof(buf)-1)
if(r<=0)
break
sendto(fd,buf,r,0,(struct sockaddr*)&addr,sizeof(addr))
}
//close socket
close(fd)
return 0
}
先运行test1.c,然后运行test2.c,在test2.c运行后输入内容,在test1.c所在终端中就会显示信息
运行结果如下:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)