zoukankan      html  css  js  c++  java
  • winsocket入门学习

    参考资料:http://c.biancheng.net/cpp/socket/

    http://www.winsocketdotnetworkprogramming.com/


    socket 是“套接字”意思,是计算机之间进行通信的一种约定。

    通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。

    学习 socket,也就是学习计算机之间如何通信,并编写出实用的程序。




    WD--返回WinSock的实现信息。

    WD是一个WSAData结构:

    typedef struct WSAData {
            WORD                    wVersion;
            WORD                    wHighVersion;
    #ifdef _WIN64
            unsigned short          iMaxSockets;
            unsigned short          iMaxUdpDg;
            char FAR *              lpVendorInfo;
            char                    szDescription[WSADESCRIPTION_LEN+1];
            char                    szSystemStatus[WSASYS_STATUS_LEN+1];
    #else
            char                    szDescription[WSADESCRIPTION_LEN+1];
            char                    szSystemStatus[WSASYS_STATUS_LEN+1];
            unsigned short          iMaxSockets;
            unsigned short          iMaxUdpDg;
            char FAR *              lpVendorInfo;
    #endif
    } WSADATA, FAR * LPWSADATA;



    最简单的WinSocket程序

    server.c

    #define _WINSOCK_DEPRECATED_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <winsock2.h>
    #pragma comment(lib, "ws2_32.lib")
    #define BUFFER_SIZE 1024
    
    int main()
    {
    	WSADATA		wsaData;			//包含系统所支持的WinSocket版本信息
    	SOCKET		sServer;			//服务器Socket,用于监听客户端请求
    	SOCKET		sClient;			//客户端Socket,用于实现与客户端的通信
    	int			retVal;				//调用各种Socket函数的返回值
    	char		buf[BUFFER_SIZE];	//用于接受客户端数据的缓冲区
    
    	//初始化WinSocket 2.2
    	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    	{
    		printf("WSAStartup failed!
    ");
    		return -1;
    	}
    
    	/**
    	*  打印socket信息
    	*  低位字节存储主版本号,高位字节存储副版本号
    	*/
    	printf("[wVersion] = %d.%d
    ", LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
    	printf("[wHighVersion] = %d.%d
    ", LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));
    	printf("[szDescription] = %s
    ", wsaData.szDescription);
    	printf("[szSystemStatus] = %s
    ", wsaData.szSystemStatus);
    	printf("[iMaxSockets] = %d
    ", wsaData.iMaxSockets);
    	printf("[iMaxUdpDg] = %d
    ", wsaData.iMaxUdpDg);
    
    	//创建用于监听的socket
    	sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    	if (sServer == INVALID_SOCKET)
    	{
    		printf("socket failed!
    ");
    		WSACleanup();
    		return -1;
    	}
    	
    	/**
    	*  设置服务器socket地址
    	*  服务器监听地址为INADDR_ANY-->在任意本地地址(0.0.0.0)监听
    	*  监听端口号为9999
    	*/
    	SOCKADDR_IN addrServ;
    	addrServ.sin_family = AF_INET;
    	addrServ.sin_port = htons(9999);
    	addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    
    	//绑定Sockets Server到本地地址
    	retVal = bind(sServer, (const struct sockaddr*)&addrServ, sizeof(SOCKADDR_IN));
    	if (retVal == SOCKET_ERROR)
    	{
    		printf("bind failed!
    ");
    		closesocket(sServer);
    		WSACleanup();
    		return -1;
    	}
    
    	//在Sockets Server上进行监听
    	retVal = listen(sServer, 1);
    	if (retVal == SOCKET_ERROR)
    	{
    		printf("listen failed!
    ");
    		closesocket(sServer);
    		WSACleanup();
    		return -1;
    	}
    
    	//接受来自客户端的请求
    	printf("TCP Server start...
    ");
    	struct sockaddr_in addrClient;
    	int addrClientlen = sizeof(addrClient);
    	sClient = accept(sServer, (struct sockaddr FAR *)&addrClient, &addrClientlen);
    	if (sClient == INVALID_SOCKET)
    	{
    		printf("accept failed!
    ");
    		closesocket(sServer);
    		WSACleanup();
    		return -1;
    	}
    
    	//printf("%s
    ", inet_ntoa(addrClient.sin_addr));
    
    	while (1)
    	{
    		//清空接收数据的缓冲区
    		memset(buf, 0, sizeof(buf));
    		retVal = recv(sClient, buf, BUFFER_SIZE, 0);
    		if (retVal == SOCKET_ERROR)
    		{
    			printf("recv failed
    ");
    			closesocket(sServer);
    			closesocket(sClient);
    			WSACleanup();
    			return -1;
    		}
    		SYSTEMTIME st;
    		GetLocalTime(&st);
    		char szDateTime[50];
    		sprintf(szDateTime, "%4d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
    			st.wHour, st.wMinute, st.wSecond);
    		
    		//打印输出信息
    		printf("%s, Recv From Client [%s:%d] :%s
    ", szDateTime, inet_ntoa(addrClient.sin_addr), addrClient.sin_port, buf);
    		
    		if (strcmp(buf, "quit") == 0)
    		{
    			send(sClient, "quit", strlen("quit"), 0);
    			break;
    		}
    		else
    		{
    			char msg[BUFFER_SIZE];
    			sprintf(msg, "Message received - %s", buf);
    			retVal = send(sClient, msg, strlen(msg), 0);
    			if (retVal == SOCKET_ERROR)
    			{
    				printf("send failed
    ");
    				closesocket(sServer);
    				closesocket(sClient);
    				WSACleanup();
    				return -1;
    			}
    		}
    	}
    
    	//清除工作
    	closesocket(sServer);
    	closesocket(sClient);
    	WSACleanup();
    
    	return 0;
    }
    client.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <winsock2.h>
    #pragma comment(lib, "ws2_32.lib")
    #define BUFFER_SIZE 1024
    
    int main()
    {
    	WSADATA		wsaData;
    	SOCKET		sHost;
    	int			retVal;
    	char		buf[BUFFER_SIZE];
    
    	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    	{
    		printf("WSAStartup failed!
    ");
    		return -1;
    	}
    
    
    	sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    	if (sHost == INVALID_SOCKET)
    	{
    		printf("socket failed!
    ");
    		WSACleanup();
    		return -1;
    	}
    	
    	SOCKADDR_IN addrServ;
    	addrServ.sin_family = AF_INET;
    	addrServ.sin_port = htons(9999);
    	addrServ.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    	
    	retVal = connect(sHost, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));
    	if (retVal == SOCKET_ERROR)
    	{
    		printf("connect failed!
    ");
    		closesocket(sHost);
    		WSACleanup();
    		return -1;
    	}
    
    	
    	while (1)
    	{
    		printf("Please input a string:");
    		gets(buf);
    		retVal = send(sHost, buf, strlen(buf), 0);
    		if (retVal == SOCKET_ERROR)
    		{
    			printf("send failed!
    ");
    			closesocket(sHost);
    			WSACleanup();
    			return -1;
    		}
    		memset(buf, 0, sizeof(buf));
    		retVal = recv(sHost, buf, sizeof(buf), 0);
    		if (retVal == SOCKET_ERROR)
    		{
    			printf("recv failed!
    ");
    			closesocket(sHost);
    			WSACleanup();
    			return -1;
    		}
    		printf("Recv From Server: %s
    ", buf);
    		if(strcmp(buf, "quit") == 0)
    		{
    			break;
    		}
    	}
    
    	//วๅณนคื๗
    	closesocket(sHost);
    	WSACleanup();
    
    	return 0;
    }

    对于完成的client/server程序可以使用NC来测试

    1)连接到 remote 主机,例子:
    格式:nc -nvv 192.168.x.x 80
    讲解:连到192.168.x.x的TCP80端口

    2)监听 local 主机,例子:
    格式:nc -l -p 80
    讲解:监听本机的TCP80端口



    Keep it simple!
    作者:N3verL4nd
    知识共享,欢迎转载。
  • 相关阅读:
    java将Thu Jun 11 00:00:00 CST 2020类型转换为正常的时间类型
    SSM中JSP和thymeleaf同时使用
    java中thymeleaf获取项目根路径
    使用position:fixed定位的DIV元素,如何使其居中
    HTML设置textarea不可拖动
    使用js让Html页面弹出小窗口
    wow.js – 让页面滚动更有趣,使用方法
    CSS修改文本框placeholder提示的文字颜色
    JS监听用户按下ESC
    当div内所有元素都是浮动的时候,让容器(div)自动适应高度
  • 原文地址:https://www.cnblogs.com/lgh1992314/p/6616395.html
Copyright © 2011-2022 走看看