Socket的使用可以分为TCP方式、UDP方式,下面就对两种使用方式进行简单的总结
1、TCP方式
TCP方式即点对点的方式,需要建立连接之后才能进行Socket通信。
服务器端:
在建立服务器端的Socket时,服务其端需要进行:
1、初始化SOCKET运行库;
2、配置通信地址;
3、创建(socket)SOCKET;
4、绑定(bind)SOCKET地址;
5、监听(listen)SOCKET地址;
6、接受(accept)SOCKET的连接;
具体实例如下:
//发送端
char name[80];
hostent* pHost;
gethostname(name,sizeof(name));//获取本机主机名
pHost = gethostbyname(name);
ip = inet_ntoa(*(struct in_addr*)pHost->h_addr_list[0]);//获取本机IP
int err;
WSADATA wsaData;
WORD wVersion;
wVersion = MAKEWORD(2,2);//生成加载的Winsock库的版本
err = WSAStartup(wVersion,&wsaData);//加载套接字库
if(err != 0){return;}
SOCKADDR_IN local_addr;
int addrsize = sizeof(SOCKADDR_IN);
local_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(5150);//绑定端口
if((listen_sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
{ //创建SOCKET失败 }
else
{ //创建SOCKET成功 }
if(bind(listen_sock,(struct sockaddr*)&local_addr,addrsize))
{//绑定SOCKET失败 }
else
{//绑定SOCKET失败 }
listen(listen_sock,1);//20160426 监听一个客户端
SOCKADDR_IN client_addr;//存储连接的客户端地址
SOCKET Client_Sock;//存储连接的客户端SOCKET
if((Client_Sock=accept(listen_sock,(struct sockaddr*)&client_addr,&addrsize))==INVALID_SOCKET)
{//服务器accept失败 }
else{
{ //服务器accept成功
//port.Format("%d",int(ntohs(client_addr.sin_port)));
//("已连接来自:"+CString(inet_ntoa(client_addr.sin_addr))+"端口:"+port);
}
//接收数据
char recvMsg[1024] = {0};
int rs = -10;
rs = recv(Client_sock, recvMsg, 1024, 0);
if(rs==-1 || rs==0){//接收数据错误}
else{recvMsg[rs] = ‘\0’}
//发送数据
if(send(Client_sock, sendMsg, strlen(sendMsg),0)==SOCKET_ERROR)
{
//发送失败
}
客户端:
在建立客户端的Socket时,服务其端需要进行:
1、初始化SOCKET运行库;
2、配置通信地址;
3、创建(socket)SOCKET;
4、连接(connect)服务器端的地址;
具体实例如下:
WSADATA wsaData;
SOCKADDR_IN server_addr;
WORD wVersion;
wVersion = MAKEWORD(2,2);
WSAStartup(wVersion,&wsaData);
server_addr.sin_addr.S_un.S_addr = inet_addr(ip);//服务端IP
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);//服务端绑定的端口
if((sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
{
printf("Error:创建SOCKET失败!\r\n");
}
else if(connect(sock,(struct sockaddr*)&server_addr,sizeof(SOCKADDR_IN))==SOCKET_ERROR)
{
printf("Error:连接服务器失败!\r\n");
}
else
{
printf(">成功连接服务器!\r\n");
}
//接收数据
char recvMsg[1024] = {0};
int rs = -10;
rs = recv(sock, recvMsg, 1024, 0);
if(rs==-1 || rs==0){//接收数据错误}
else{recvMsg[rs] = ‘\0’}
//发送数据
if(send(sock, sendMsg, strlen(sendMsg),0)==SOCKET_ERROR)
{
//发送失败
}
2、UDP方式
UDP的通讯方式不需要提前建立连接即可发送、接收数据。当需要数据传输时,只需要向某地址发送数据即可,
当接收方发现接收缓存区中有数据时,就会把数据读取出来。这种模式数据传输比较快,但可靠型略低,可能会造成丢包。
当采用UDP方式时,并没有严格的服务器、客户端之分;为了方便理解,可以理解为发送方、接收方。
服务器端:
在建立服务器端的Socket时,服务其端需要进行:
1、初始化SOCKET运行库;
2、配置通信地址;
3、创建(socket)SOCKET;
4、发送数据(sendto);
具体实例如下:
WSADATA wsaData;
WORD wVersion;
wVersion = MAKEWORD(2,2);
if(WSAStartup(wVersion,&wsaData) != 0)
{
UpdateStatus("初始化SOCKET失败!");
exit(1);
}
SOCKET SockUdp;
SOCKADDR_IN serverAddr;
int addrsize = sizeof(SOCKADDR_IN);
if((SockUdp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
{
UpdateStatus("创建UDP-SOCKET失败!");
return;
}
//for send
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.S_un.S_addr = inet_addr("接收端IP地址");
serverAddr.sin_port = htons(9000); // 接收端端口号
//发送数据
int fromlength=sizeof(serverAddr);
sendto(SockUdp, sendMsg, strlen(sendMsg), 0, (struct sockaddr FAR *)&serverAddr, fromlength);
客户端:
在建立客户端的Socket时,服务其端需要进行:
1、初始化SOCKET运行库;
2、配置通信地址;
3、创建(socket)SOCKET;
4、绑定(bind)接收地址;
5、接收数据(recvFrom)
具体实例如下:
WSADATA wsaData;
WORD wVersion = MAKEWORD(2,2);
WSAStartup(wVersion,&wsaData);
SOCKET sock;
SOCKADDR_IN recvAddr; // 接收端(客户端)的地址
SOCKADDR_IN sendAddr; // 发送端(服务端)的地址,只用于存储
if((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==INVALID_SOCKET)
{
printf("》创建 UDP SOCKET 失败!\r\n");
}
int nlen=sizeof(SOCKADDR_IN);
//用来从网络上的广播地址接收消息
recvAddr.sin_family = AF_INET;
recvAddr.sin_addr.S_un.S_addr = inet_addr("本机接收IP地址");//接收数据端可以以这种方式设置
recvAddr.sin_port = htons(9000); // 本机接收数据的端口号
//bind
if (bind(sock, (SOCKADDR*)&recvAddr, sizeof(recvAddr)) != 0)
{
printf("》bind error:%d\n", err);
closesocket(sock);
WSACleanup();
}
//接收数据
int res = -10;
int addr_len=sizeof(SOCKADDR_IN);
char recvMsg[1024] = {0};
res = recvfrom(sock, recvMsg,1024, 0, (struct sockaddr *)&sendAddr, &addr_len);
if( res == SOCKET_ERROR)
{
UpdateStatus("》未正确接收数据!");
int err = WSAGetLastError();
break;
}
else if(res > 0)
{//数据接收成功
//recvMsg[res] = ‘\0’;
}
3、备注
无论采取什么方式,都必须包含头文件: Winsock2.h
同时需要加载ws2_32.lib文件:#pragma comment(lib, "ws2_32.lib")
在创建SOCKET时。TCP方式的第二个参数为SOCK_STREAM,UDP方式的第二个参数为SOCK_DGRAM.
TCP方式下,在服务器端需要绑定地址,而对于UDP方式来说,只要接收数据,就需要绑定接收地址