TCP多線程服務器
C-S模型
c-s模型即客戶-服務器模型,要實現他們之間的通信,服務器端和客戶端各需要完成以下的工作:
服務器端需完成的工作
socket:建立套接字bind:發佈端口
listen:開始偵聽
accept:接納客戶端連接
send/recv/recvfrom:收發數據
socket:建立套接字
bind:發佈端口
connect:連接到服務器
send/recv/recvfrom:收發數據
三次握手通信的流程如下圖
單線程服務器請參照這篇文章:http://blog.csdn.net/ccsuxwz/article/details/65937565
實現多線程服務器需要用到線程函數
每有一個新的客戶端連接上,就需要爲該連接開闢一個新的線程,每個客戶端需要建立連接後才能與服務器端進行通信。
下面是具體實現:
/*
*multi-server.cpp
*2017年6月11日
*author:xwz
*編譯器:vs2015
*/
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
#include<WinSock2.h>
#include<process.h>
using namespace std;
enum{PORT = 8621};
void thread_fun(void *p)
{
char s[1024];
SOCKET socka = (SOCKET)p;
char *str = "hello client!";
sockaddr_in sa = { AF_INET };
int n_Len = sizeof(sa);
send(socka, str, strlen(str), 0);
getpeername(socka, (sockaddr*)&sa, &n_Len);
cout << inet_ntoa(sa.sin_addr) << "-" << htons(sa.sin_port) << "登錄:" << endl;
while (true) //循環發送數據
{
int i = recv(socka, s, sizeof(s), 0);
if (i <= 0)
{
cout << GetLastError() << endl;
cout << inet_ntoa(sa.sin_addr) << "-" << htons(sa.sin_port) << "退出:" << endl;
break;
}
s[i] = 0;
cout << inet_ntoa(sa.sin_addr) << "-" << htons(sa.sin_port)<< "說:" << s << endl;
}
}
int main()
{
WSADATA wd;
WSAStartup(0x0202, &wd); //初始化加載ws2_32.lib
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); //初始化套接字
if (sock == INVALID_SOCKET)
{
cout << GetLastError() << endl;
return -1;
}
sockaddr_in sa = { AF_INET,htons(PORT) };
if (bind(sock, (sockaddr*)&sa, sizeof(sa)) < 0) //綁定端口
{
cout << GetLastError() << endl;
return -1;
}
listen(sock, 5); //監聽
while (true)
{
SOCKET socka = accept(sock,0,NULL); //通信套接字
_beginthread(thread_fun, 0, (void*)socka); //創建線程
}
return 0;
}
/*multi-client.cpp*/
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
#include<WinSock2.h>
using namespace std;
enum { PORT = 8621 };
int main()
{
WSADATA wd;
WSAStartup(0x0202, &wd); //初始化加載ws2_32.lib
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); //初始化套接字
if (sock == INVALID_SOCKET)
{
cout << GetLastError() << endl;
return -1;
}
sockaddr_in sa = { AF_INET,htons(PORT) }; //指明地址信息
sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int n_Len = sizeof(sa);
if(SOCKET_ERROR ==connect(sock, (sockaddr*)&sa, n_Len)) //連接
{
cout << GetLastError() << endl;
return -1;
}
char s[1024];
int n = recv(sock, s, sizeof(s), 0); //接收數據
if (n > 0)
{
s[n] = 0;
cout << s << endl;
}
while (true)
{
cout << "請輸入要發送的內容:";
cin >> s;
send(sock, s, strlen(s), 0);
}
return 0;
}