• 完美实现 Windows 下网络通信


    编译环境:DEV C++

    配置编译器

    Windows 下 实现 Socket 编译需要 ws2_32.lib 这个库的支撑,所以我们编译前应该配置下编译器,具体配置步骤如下:

    Tools -> Compiler Options
    

    加入 -l 链接,如图所示:

    实现的功能

    服务器端与客户端可以互相自由给对方发送消息,无需在意接收与发送的顺序(利用线程实现)!可以实现加法运算。如需其它的功能,可以自行补充,如:实现四则运算、文件传输等。

    服务器程序

    /*
    	Name: TCP Server 
    	Copyright: -lws2_32
    	Author: Lance#
    	Date: 18/05/18
    	Description: TCP Server 
    */
    
    #include <stdio.h>    
    #include <winsock2.h> 
    #include <windows.h>
    #include <string.h>
    
    #define PORT		8080  
    #define BUFSIZE		1024
    
    /* 客户端Socket与发送缓冲 */
    SOCKET client;
    unsigned char SendBuf[BUFSIZE+1];
    
    enum{
    	NoConnection,
    	Connected,
    }LinkStatus;
    
    /* 客户端连接状态监控线程 */
    DWORD WINAPI print_message(LPVOID arg)
    {
    	while(1){
    		if(!LinkStatus){
    			printf("	等待客户端连接 .... 
    ");
    			sleep(1);
    		}
    	}
    }
    
    /* 服务器发送消息线程 */
    DWORD WINAPI send_message(LPVOID arg)
    {	
    	while(1){
    		memset(SendBuf, 0, 1024); 
    		fgets(SendBuf, 1024, stdin);
        	send(client, SendBuf, 1024, 0);
    	}
    } 
    
    int main(int argc, char* argv[])
    {
        WSADATA wsaData;
        struct sockaddr_in sin_addr;
        struct sockaddr_in remoteAddr;
        unsigned char recvData[BUFSIZE+1];
    	int nAddrlen = sizeof(remoteAddr);
    	
    	unsigned int num_l, num_r;
    	unsigned char sum_buf[100] = {0};
    	
    	/* 线程标识 */
    	HANDLE pthread;
    	
        /* 启动 WSA */
        WORD sockVersion = MAKEWORD(2, 2);
    
        if (WSAStartup(sockVersion, &wsaData)){
        	perror("WSA boot failed!");
            return -1;
        }
    
        /* 创建服务端套接字 */
        SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (server == INVALID_SOCKET){
            perror("socket error!");
            return -1;
        }
    
        /* 配置 sin_addr */
        sin_addr.sin_family = AF_INET;
        sin_addr.sin_port = htons(PORT);
        /* 可监听任意的地址 */
        sin_addr.sin_addr.S_un.S_addr = INADDR_ANY; 
        /* 监听指定的地址 */
    //    sin_addr.sin_addr.S_un.S_addr = inet_addr("192.168.1.149"); 
        
        /* 绑定 */
        if (bind(server, (LPSOCKADDR)&sin_addr, sizeof(sin_addr)) == SOCKET_ERROR){
            perror("bind error!");
            return -1;
        }
    
        /* 监听 */
        if (listen(server, 100) == SOCKET_ERROR){
            perror("listen error!");
            return -1;
        }
        
        puts("服务器成功启动"); 
        
        /* 创建状态线程 */
        CreateThread(NULL,0,print_message,NULL,0,NULL);
        /* 创建消息线程 */
        pthread = CreateThread(NULL,0,send_message,NULL,0,NULL);
    
        while (1)
    	{	
            LinkStatus = NoConnection;
            client = accept(server, (SOCKADDR *)&remoteAddr, &nAddrlen);
            LinkStatus = Connected;
            
            if (client == INVALID_SOCKET)
            {
                perror("accept error!");
                continue;
            }
            
            printf("客户端:%s 已连接
    ", inet_ntoa(remoteAddr.sin_addr));
    
    		while(1){
    
    	        /* 数据接收 */
    	        memset(recvData, 0, sizeof(recvData));
    	        int ret = recv(client, recvData, 1024, 0);
    	        if (ret > 0){
    	            printf("Recv:	%s", recvData);
    	            /* 实现加法运算,客户端发来  "%d + %d =" 形式的数据后,将结果返回至客户端 */
    	            if(sscanf(recvData, "%d + %d =", &num_l, &num_r) == 2){
    	            	sprintf(sum_buf, "%d + %d ,sum is %d", num_l, num_r, num_l + num_r);
    	            	send(client, sum_buf, sizeof(sum_buf), 0);
    	            	memset(sum_buf, 0, sizeof(sum_buf));
    				}
    			}else
    	        	/* 客户端异常则断开当前连接 */
    				goto Reconnect;
    				
    			/* 客户端要求退出的话则断开当前连接 */
    			if(!strncmp(recvData, "quit", 4))
    				goto Reconnect;
    		}
    		
    	Reconnect:
    		closesocket(client);
    		puts("*** 客户端已断开");
        }
    
    	/* 关闭服务器套接字 */
        closesocket(server); 
        WSACleanup();
        
        return 0;
    }
    

    客户端程序

    /*
    	Name: TCP Client 
    	Copyright: -lws2_32
    	Author: Lance#
    	Date: 18/05/18
    	Description: TCP Client
    */
    
    #include <stdio.h>  
    #include <winsock2.h>  
    #include <Windows.h>  
    #include <string.h>
      
    #define PORT 		8080  
    #define BUFSIZE		1024
    
    unsigned char recvData[BUFSIZE+1] = {0};  
    
    /* 线程标识 */
    HANDLE pthread;
    
    DWORD WINAPI recv_message(LPVOID arg)
    {
    	int res;
    	
    	while(1){
    		memset(recvData, 0, 1024); 
    		res = recv((SOCKET)arg, recvData, 1024, 0);
    		if(res > 0)
    			printf("Recv:	%s", recvData);
    		else{
    			printf("*** 服务器已退出(回车退出程序)");
    			return 0;
    		} 
    	}
    }
      
    int main(int argc, char * argv[])  
    {  
    	unsigned char SendBuf[BUFSIZE+1] = {0};  
    	WSADATA wsaData;
    	SOCKADDR_IN addrServ;  
    	
    	if(argc != 2){
    		puts("argc error");
    		puts("Usage: <client.exe> <ip addr>");
    		return -1;
    	}
    
        /* 启动 WSA */
        WORD sockVersion = MAKEWORD(2, 2);
    
        if (WSAStartup(sockVersion, &wsaData)){
        	perror("WSA boot failed!");
            return -1;
        }
        
        /* 创建 socket */
        SOCKET client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
        if (client == INVALID_SOCKET){  
            perror("socket failed");  
            return -1;  
        }  
        
        /* 配置 socket */
        addrServ.sin_family = AF_INET;  
        addrServ.sin_port = htons(PORT);  
    	/* 配置服务器 IP */
        addrServ.sin_addr.S_un.S_addr = inet_addr(argv[1]);  
          
        /* 连接至服务器 */
        int ret = connect(client,(SOCKADDR*)&addrServ,sizeof(SOCKADDR));
        if (SOCKET_ERROR == ret){  
            perror("socket connect failed");  
            closesocket(client);  
            WSACleanup();  
            return -1;  
        }  
        
        /* 创建工作线程 */
    	pthread = CreateThread(NULL,0 ,recv_message,(LPVOID)client,0,NULL);
    	
    	puts("客户端成功启动,输入'quit'关闭客户端"); 
        
        while(1)
    	{
    	    memset(SendBuf,0,sizeof(SendBuf));  
    	    
    	    fgets(SendBuf, 1024, stdin);
    	    
    	    ret = send(client, SendBuf, 1024, 0);  
    	    if (SOCKET_ERROR == ret){  
    	        closesocket(client);  
    	        exit(0);
    	    } 
    		
    		/* 客户端退出 */
    		if(!strncmp(SendBuf, "quit", 4))
    			goto Disconnect;
    	}
    
    Disconnect:  
        closesocket(client);  
        WSACleanup();  
        
        return 0;  
    }  
    

    运行结果演示

    打开 CMD,进入可执行文件所在目录

    执行 server.exe 运行服务器;
    启动另一个 CMD,执行 client.exe 127.0.0.1 运行客户端。

    双方可进行通信,效果如图:

  • 相关阅读:
    合代码、merge代码
    springboot 获取项目版本
    软考复习思路之疫情来的太突然之备战明年软考中级之软件设计师
    供应链管理笔记 概述2
    供应链管理笔记
    供应链管理 流程与实施1
    Winform中内嵌显示Office
    数据库提交数据注意事项
    工业互联网
    C#利用using System.Net实现Json数据提交WebAPI
  • 原文地址:https://www.cnblogs.com/GyForever1004/p/9082360.html
Copyright © 2020-2023  润新知