在Windows下利用visual studio完後socket服務器的搭建(可連接多個客戶端)

socket服務器其實網上有很多的代碼,但是大部分是基於Linux的,或者是Windows下的c++語言完成的設計,而且大部分是一對一的連接。今天發表一個C語言完成的socket服務器,可以實現一對多,多個客戶端可以用IP和發送的數據來區分不同。另外,我的多客戶端不是選擇進程和多線程的辦法,但是對於有需要的,我會添加線程和進程的使用。

注意:這是vs2017的環境,但是對於Windows大部分的編譯器來說,是沒有問題的,如果不行,對於報錯的信息進行修改就可以了。如果是Linux的系統下,需要改的稍微多一點,但是萬變不離其宗,基本上就是頭文件名,參數和函數名的修改,整體的結構是我實驗了很多次的。

1.socket服務器的代碼 (一對一)

#include"pch.h"

#include <stdio.h>
#include <winsock2.h>
//#include<iostream>
//#define MaxSize 10000

#pragma comment(lib,"ws2_32.lib")

#define _WINSOCK_DEPRECATED_NO_WARNINGS//解決:inet_ntoa函數和無法使用inet_ntop的問題




int main(int argc, char* argv[])
{
	//初始化WSA
	WORD sockVersion = MAKEWORD(2, 2);//操作系統根據請求的Socket版本來搜索相應的Socket庫,
									  //然後綁定找到的Socket庫到該應用程序中。
									  //以後應用程序就可以調用所請求的Socket庫中的其它Socket函數
	WSADATA wsaData;//WSADATA是一種數據結構,存儲WSAStartup函數返回的數據
	if (WSAStartup(sockVersion, &wsaData) != 0)//第一個參數是版本號,第二個參數是保存start的返回值
	{
		return 0;
	}

	//創建套接字
	SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//創建面向網絡的套接字,而且是有連接的,協議自然爲TCP協議
	if (slisten == INVALID_SOCKET)//判斷套接字是否創建成功
	{
		printf("socket error !");
		return 0;
	}

	//綁定IP和端口
	sockaddr_in sin;//處理網絡通信地址的結構體,聲明變量
	sin.sin_family = AF_INET;// TCP/IP協議族
	sin.sin_port = htons(80);//端口可以自己賦值
	sin.sin_addr.S_un.S_addr = INADDR_ANY;//設置的是服務器的IP地址,inet_addr("0.0.0.0"); 本地的IP地址是
										   //服務器端計算機上的所有網卡的IP地址都可以作爲服務器IP地址
	if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)//綁定並進行判斷,套接字指向sockaddr_in結構體的指針,參數長度 
	{
		printf("bind error !");
	}

	for (int i=0; i<10;i++)
	{//開始監聽
		if (listen(slisten, 10) == SOCKET_ERROR)//監聽一個主動連接的套接字,一個隊列內核上限(slisten 變爲監聽套接字)
		{
			printf("listen error !");
			return 0;
		}

		//循環接收數據
		SOCKET sClient;
		sockaddr_in remoteAddr;
		int nAddrlen = sizeof(remoteAddr);
		char revData[255];

		printf("等待連接...\n");
		sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);//返回值:連接套接字;參數:監聽套接字,ADDR結構體,ADDR結構體的大小
		if (sClient == INVALID_SOCKET)//爲空,繼續
		{
			printf("accept error !");
			//continue;
		}
		printf("接受到一個連接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));
		while (true)
		{
			//接收數據
			int ret = recv(sClient, revData, 1024, 0);//指定套接字,接收的數據,buf,一般爲0
			//printf("%s", &revData);
			if (ret > 0)
			{
				revData[ret] = 0x00;
				printf(revData);//顯示接收的數據
				printf("\n");
			}

			//發送數據
			const char * sendData = revData;//對於客戶端發送過來的數據,再原樣反饋回去。

			send(sClient, sendData, strlen(sendData), 0);//參數說明:套接字,發送數據,長度,一般爲0

			if (sClient == INVALID_SOCKET)//爲空,繼續
			{
				printf("listen error !");
				break;

			}
//			closesocket(sClient);
		}
		closesocket(sClient);
	}

	closesocket(slisten);//關閉
	WSACleanup();//清除
	return 0;

}

這是一對一連接成功的結果圖,有問題的可以聯繫我。

代碼編譯的控制檯                                      一個仿真軟件做客戶端,也可以自己寫

2.進程的使用方法



		/*如果想使用多線程,可以在原有的基礎上進行新的函數定義,然後用下面的辦法創建,其中會有一些聲明和變量的定義,可以通過編譯器的報錯來修改,基本上沒有什麼大問題了。當然,你要使用互斥鎖可能難度更大一些*/
		HANDLE hThread01 = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)send, (LPVOID)sClient, 0, 0);//發送,send就是你所編輯的函數,可以替換,sclient就是你的創建的接收的數據套接字,也可修改
		if (hThread1 != NULL)
		{
			CloseHandle(hThread1);
		}
		HANDLE hThread02 = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)recv, (LPVOID)sClient, 0, 0);//接收,類比第一個線程
		if (hThread2 != NULL)
		{
			CloseHandle(hThread2);
		}
		Sleep(1000);	//must

3.一對多服務器,可以打開多個客戶端連接

在一對一的基礎上,可以使用線程的辦法,實現一個服務器多個客戶端,但是線程挺難的,所以說,我沒有理解透徹,就換了一個辦法,在Windows的環境下可以,在Linux的環境下,稍微修改一下頭文件和函數名也可以實現。我這裏給出Windows下一對多的服務器代碼。

服務器的代碼網址:https://download.csdn.net/download/jinfu5225/12342650

客戶端是用的sscom仿真軟件,這樣的話,比較方便,有需要的下載:https://download.csdn.net/download/jinfu5225/12342561

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章