前面我们使用TCP实现C/S通信
接下来,我们将使用UDP
使用UDP实现数据的收发,我们不用区分客户端和服务器(客户端和服务器端集合在一起)
写代码中存在的陷阱:
1.发送和接收的SOCKET 需要单独设置。发送SOCKET 为对方IP,接受SOCKET为本机IP
2.端口绑定,只需要对接受端进行端口绑定
3.sendto发送数据的大小需要使用strlen()而不能使用sizeof(),防止出现发送无用数据
4.recvfrom接受数据的大小使用sizeof(),因为此时strlen(buf)的大小为0,不可使用
5.recvfrom注意接受数据buf的长度,若小于数据的长度,会返回-1
#include <iostream>
#include <winsock2.h>
#pragma comment (lib,"WS2_32.lib")
#define SERVER_IP "127.0.0.1" /* 接受方PC主机的IP地址 */
#define SERVER_PORT (8000) /* PC主机的IP端口 */
SOCKET clientsocket;
SOCKET serversocket;
SOCKADDR_IN client_addr;
SOCKADDR_IN server_addr;
DWORD WINAPI SendFun(LPVOID)
{
clientsocket = socket(AF_INET, SOCK_DGRAM, 0);
client_addr.sin_family = AF_INET;
client_addr.sin_addr.S_un.S_addr = inet_addr(SERVER_IP); //接受方IP
client_addr.sin_port = htons(SERVER_PORT);
/*同一台电脑端口只能绑定一次,否则无法和自己通信
bind(clientsocket, (SOCKADDR *)&client_addr, sizeof(client_addr));*/
char buf[100] = "";
while (1)
{
memset(buf, 0, 100);
scanf("%s", buf);
//使用strlen发送实际数据长度
int ret = sendto(clientsocket, buf, strlen(buf), 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
if (ret < 0) {
printf("send data error");
}
Sleep(100);
}
return 0;
}
DWORD WINAPI RevFun(LPVOID)
{
int len = sizeof(SOCKADDR);
serversocket = socket(AF_INET, SOCK_DGRAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //监听本地端口的IP
server_addr.sin_port = htons(SERVER_PORT);
bind(serversocket, (SOCKADDR *)&server_addr, sizeof(server_addr));//监听本地端口的IP
char buf[100] = "";
while (1)
{
memset(buf, 0, 100);
//如果接收到数据的大于buf,ret返回值为-1
int ret = recvfrom(serversocket, buf, sizeof(buf), 0, (SOCKADDR *)&server_addr, &len);
if (ret < 0) {
printf("recv data error");
}
printf("%d\n%s\n", ret, buf);
Sleep(100);
}
return 0;
}
int main(int argc, char *argv[])
{
WSADATA wsadata;
WSAStartup(MAKEWORD(2, 2), &wsadata);
HANDLE Send_Thread = CreateThread(NULL, 0, SendFun, 0, 0, NULL);
HANDLE Rev_Thread = CreateThread(NULL, 0, RevFun, 0, 0, NULL);
WaitForSingleObject(Rev_Thread, INFINITE);
WSACleanup();
return 0;
}