zoukankan      html  css  js  c++  java
  • Winsock网络编程笔记 : 基于TCP的 Client

    每次写网络程序都必须编写代码载入和释放winsock库,为了以后方便使用,我们将封装一个CInitSock类来管理Winsock库: 

    // initsock.h文件
     
    #include <winsock2.h>
    #pragma comment(lib, "WS2_32")	// 链接到WS2_32.lib
     
    class CInitSock		
    {
    public:
    	CInitSock(BYTE minorVer = 2, BYTE majorVer = 2)
    	{
    		// 初始化WS2_32.dll
    		WSADATA wsaData;
    		WORD sockVersion = MAKEWORD(minorVer, majorVer);
    		if(::WSAStartup(sockVersion, &wsaData) != 0)
    		{
    			exit(0);
    		}
    	}
    	~CInitSock()
    	{	
    		::WSACleanup();	
    	}
    };
    #include"../common/initsock.h"
    #include<iostream>
    using namespace std;
    
    CInitSock initSock;
    
    int main()
    {
    	SOCKET s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //创建socket套接字s
    	if (s == INVALID_SOCKET)
    	{
    		cout << "创建socket失败!" << endl;
    		return 0;
    	}
    	sockaddr_in serverAddress;                       //创建服务器地址
    	serverAddress.sin_family = AF_INET;              //sin_family指代协议族,在socket编程中只能是AF_INET
    	serverAddress.sin_port = htons(4567);             //绑定服务器端口号
    	serverAddress.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //绑定服务器IP地址,sin_addr用的是in_addr的结构储存IP
    
    	if (::connect(s, (sockaddr*)&serverAddress, sizeof(serverAddress)) == -1)//初始化serverAddress并判断connect函数返回值
    	{
    		cout << "客户端连接失败!" << endl;
    		return 0;
    	}
    	char receivedData[256];
    	int index = ::recv(s, receivedData, 256, 0);
    	if (index > 0)
    	{
    		receivedData[index] = '';
    		cout << "接收到来自服务端的数据为: " << receivedData << endl;
    	}
    	::closesocket(s);
    	return 0;
    }

     

    部分函数详解:

    struct sockaddr_in

    struct sockaddr_in
    {
        short sin_family;
    /*Address family一般来说AF_INET(地址族)PF_INET(协议族),在socket编程中只能是AF_INET*/
     
        unsigned short sin_port;
    /*Port number(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字),
        sin_port存储端口号(使用网络字节顺序),在linux下,端口号的范围0~65535,同时0~1024范围的
        端口号已经被系统使用或保留。*/
     
        struct in_addr sin_addr;
    /*sin_addr存储IP地址,使用in_addr这个数据结构*/
     
        unsigned char sin_zero[8];
    /*Same size as struct sockaddr没有实际意义,只是为了跟SOCKADDR结构在内存中对齐*/
    };
    
    
    sockaddr_in和sockaddr是并列的结构,指向sockaddr_in的结构体的指针也可以指向sockaddr的结构体,
    并代替它。也就是说,你可以使用sockaddr_in建立你所需要的信息,然后用memset函数初始化就可以了。
    
    
    memset((char*)&mysock,0,sizeof(mysock));//初始化
    
    sockaddr_in mysock;
    memset((char*)&mysock,0,sizeof(mysock));
    mysock.sin_family=AF_INET;
    mysock.sin_port=htons(1234);//1234是端口号
    mysock.sin_addr.s_addr=inet_addr("192.168.0.1");

     inet_addr()

    in_addr_t  inet_addr(const char* strptr);
    
    /*inet_addr方法可以转化字符串,主要用来将一个十进制的数转化为二进制的数,用途多于ipv4的IP转化。*/
    返回:若字符串有效则将字符串转换为32位二进制网络字节序的IPV4地址,否则为INADDR_NONE
    
    struct in_addr{
        in_addr_t   s_addr;
    }
    
    所处头文件: #include <arpa/inet.h>
    
    例子:
    daddr.s_addr = inet_addr("192.168.1.60");

     connect

    int connect(
      __in          SOCKET s,
      __in          const struct sockaddr* name,
      __in          int namelen
    );
    
    SOCKET:标识一个套接字。
    serv_addr:套接字s想要连接的主机地址和端口号。
    namelen:name缓冲区的长度。

    recv

    int recv(
      __in          SOCKET s,
      __out         char* buf,
      __in          int len,
      __in          int flags
    );
    
    不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。该函数的第一个参数指定接收端套接字描述符;
    第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
    第三个参数指明buf的长度;
    第四个参数一般置0。
  • 相关阅读:
    155. 最小栈
    160. 相交链表
    PAT 1057 Stack
    PAT 1026 Table Tennis
    PAT 1017 Queueing at Bank
    PAT 1014 Waiting in Line
    PAT 1029 Median
    PAT 1016 Phone Bills
    PAT 1010 Radix
    PAT 1122 Hamiltonian Cycle
  • 原文地址:https://www.cnblogs.com/Romantic-Chopin/p/12451013.html
Copyright © 2011-2022 走看看