TCP多線程服務器

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;
}



發佈了64 篇原創文章 · 獲贊 141 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章