本代码为tcp服务器端的C++代码,代码实现的功能是接受客户端的请求,当客户端发送来的信息时,回复“OK”字符串。
服务器端工作原理:
服务器首先开启一个socket,并一直监听这个socket。这时,程序在accept处阻塞。当有请求过来时,就会accept成功。accept成功后会返回一个新的socket,这个新的socket负责服务器与这个客户端的通讯。这时主线程新建一个子线程,并将新的socket传给这个子线程,在这个子线程中进行服务器与这个客户端的通讯工作。
下面是服务器端代码:
/*Server*/
#include <stdio.h>
#include <WinSock2.h>
#include <process.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
int InitWinSocket()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);//第一个参数为低位字节;第二个参数为高位字节
err = WSAStartup(wVersionRequested, &wsaData);//对winsock DLL(动态链接库文件)进行初始化,协商Winsock的版本支持,并分配必要的资源
if (err != 0)
{
return -1;
}
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)//LOBYTE()取得16进制数最低位;HIBYTE()取得16进制数最高(最左边)那个字节的内容
{
WSACleanup();
return -1;
}
return 0;
}
unsigned _stdcall WorkProc(LPVOID args)
{
SOCKET* workSock = (SOCKET*)args;
char buf[64];
while (1)
{
/*收到请求*/
memset(buf, 0, sizeof(buf));
recv(*workSock, buf, sizeof(buf), 0);
printf("recv: %s\n", buf);
/*回复请求*/
memset(buf, 0, sizeof(buf));
sprintf_s(buf, "%s", "OK");
send(*workSock, buf, strlen(buf), 0);
}
closesocket(*workSock);
}
int main()
{
/*初始化 Windows Socket*/
if (InitWinSocket() != 0)
{
printf("Init Windows Sock Failed!\n");
return -1;
}
printf("Server:\n");
SOCKET sock;
sockaddr_in server;
sockaddr_in client;
int addr_len = sizeof(SOCKADDR);
/*创建socket*/
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0)
{
printf("create socket failed!\n");
return -1;
}
/*对socket进行一些设置,这里是端口复用设置*/
int opt = 1;
socklen_t optlen = sizeof(opt);
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, optlen) < 0)
{
printf("set sock opt failed!\n");
return -1;
}
/*设置服务器ip和端口*/
server.sin_family = AF_INET;
server.sin_port = htons(9555);
server.sin_addr.s_addr = 0;
/*绑定服务器地址和socket*/
if (bind(sock, (sockaddr*)&server, addr_len) < 0)
{
printf("binding socket failed!\n");
return -1;
}
/*开启监听*/
listen(sock, 16);//第二个参数是未完成队列的大小
while (1)
{
SOCKET workSock = accept(sock, (SOCKADDR*)&client, &addr_len);
if (workSock < 0)
{
return -1;
}
/*新建一个线程,把与该客户端通讯的工作放到这个线程里*/
HANDLE h = (HANDLE)_beginthreadex(NULL, 0, WorkProc, (void*)&workSock, NULL, NULL);
}
WSACleanup();
return 0;
}