WinSocket编程笔记(二)

bind 绑定函数(服务器端专属函数,有三种结构体,这里只介绍一种)

通常,在一个SOCK_STREAM套接字接收连接之前,必须通过bind()函数用本地地址为套接字命名

sockaddr_in 结构体

定义内容:

sin_family 地址族: 与socket()的第一个参数相同含义,必须为 AF_INET
sin_port 端口号
sin_addr IPv4 地址
sin_zero[8] 对齐

实例定义:

SOCKET ListenSocket = socket(AF_INET,SOCK_STREAM,0);
sockaddr_in sockAddr;//结构体名称为sockAddr sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(8888);//默认为htons(PORT)

sockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//默认为INADDR_ANY
int n;//这里定义n是为了判断是否出错,可直接调用bind(),不用n=bind()

 n=bind(ListenSocket,(LPSOCKADDR)&sockAddr,sizeof(sockAddr));
 if(n==SOCKET_ERROR){
 cout<<"false"<<endl;
 return -1;
 }
 else{
 cout<<"端口绑定成功:"<<PORT<<endl;
 }

 注:为了简化编程一般将IP地址设置为INADDR_ANY,如果需要使用特定的IP地址则需要使用inet_addr 和inet_ntoa完成字符串和in_addr结构体的互换

listen 监听函数

函数原型:

int listen(int sockfd/*已绑定但未监听的套接字*/, int backlog/*挂起连接队列的最大长度*/)

定义实例:

int listenStatus = listen(mySocket,10);//listen的是bind的socket名
if(listenStatus == SOCKET_ERROR){
    cout<<"listen error";
    ...
    WSACleanup();
}

accept 接收连接请求(只存在服务器端,与客户端的connect一起使用)

函数原型:

SOCKET accept(

       SOCKET s,

       struct sockaddr FAR *addr,

       int FAR *addrlen

);

定义实例:

listen(Socket, 20); 
SOCKET serverocket;//新建socket
SOCKADDR clntAddr; //新建结构体
int nSize = sizeof(SOCKADDR); //结构体长度
cout << "Wait connection" << endl;
serverocket = accept(Socket/*listen的第一个参数名*/, (SOCKADDR*)&clntAddr/*结构体*/, &nSize/*结构体长度*/);

connect 请求连接函数(客户端函数,和accept一起使用)

客户端请求与服务器端建立连接

  • socket 若未绑定, 操作系统赋值绑定
  • addr 服务器端的地址结构
  • addrlen 服务器端地址长度
  • 返回值
    • 成功: 返回 0
    • 失败: 返回 SOCKET_ERROR

函数原型:

int connect(SOCKET s,const struct sockaddr *name,int namelen);
//说明:第一个参数是套接字,
//第二个是包含地址信息的sockaddr_in结构体,
//第三个 是sockaddr_in结构体长度;

//返回值: 正常返回0, 错误返回SOCKET_ERR,也就是-1,

定义实例:

sockaddr_in server;
        server.sin_family = AF_INET;
        server.sin_port = htons(8828);
        server.sin_addr.s_addr = inet_addr("127.0.0.1");
        if (connect(cnetsocket,(sockaddr*)&server,sizeof(server)) == SOCKET_ERROR)
        {
            break;
        }

send 发送数据函数

函数原型:

int send(SOCKET S, const char *buf , int len, int flags)
  • 已连接的 socket
  • buf 待发送缓冲区
  • len 待发送内容长度
  • flags 选项, 一般为0

定义实例:

char buff[1024] = {"abcdefghijklmnopqrstuvwxyz"};

int sent = 0;//已发送

int total_size = sizeof(buff);

sent = send(sock, buff+sent, total_size - sent, 0);

 

recv 接收数据函数

在已建立连接的 socket 上接收数据

函数原型:

int recv( SOCKET s,char* buf,int len,int flags);   
  • 已连接的 socket
  • buf 接受缓冲区
  • len 缓冲区长度
  • flags 选项, 一般为 0
      返回值
      • 成功: 返回实际接收的字节数
      • 连接已终止: 0
      • 失败: 返回 SOCKET_ERROR

定义实例:

char buffer[BUFFER_SIZE];
memset(buffer, 0, BUFFER_SIZE);//这一步是初始化,不一定需要 n
= recv(clntSocket/*注意这里的socket名称是定义的accept socket*/, buffer, BUFFER_SIZE, 0)

实战(以之前内容为基础,编写回射程序,且服务器端能打印客户端的ip和端口)

注:exe程序执行成功后自动退出,请在编译器里调试查看结果

服务器:

#include <iostream>
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define BUF_SIZE 100
const int PORT = 8000;
int main()
{
    WORD sockVersion = MAKEWORD(2, 2);

    WSADATA data;

    if (WSAStartup(sockVersion, &data) != 0)

    {

        return 1;

    }
    SOCKET serverSocket = socket(AF_INET, SOCK_STREAM,0);
        if (serverSocket == INVALID_SOCKET){
            cout << "Socket error" << endl;}
    SOCKADDR_IN ListenAddr;
    ListenAddr.sin_family=AF_INET;
    ListenAddr.sin_addr.S_un.S_addr=INADDR_ANY;
    ListenAddr.sin_port=htons(PORT);
//绑定socket
    int n;
    n=bind(serverSocket,(LPSOCKADDR)&ListenAddr,sizeof(ListenAddr));
    if(n==SOCKET_ERROR)
        {
            return false;
        }
    else{
    cout<<"端口绑定成功:"<<PORT<<endl;
    }
//监听端口
    listen(serverSocket,20);
    struct sockaddr_in addrClient;
    int len = sizeof(struct sockaddr_in);
//accept
    int sockConn = accept(serverSocket, (struct sockaddr *)&addrClient, &len);
    cout<<"ip="<<inet_ntoa(addrClient.sin_addr)<<endl;
    cout<<"port="<<ntohs(addrClient.sin_port)<<endl;
//recv
    char buffer[BUF_SIZE];
    int m=recv(sockConn, buffer, BUF_SIZE, 0);
    if(m==SOCKET_ERROR)
        {
           return false;
        }
//send
    send(sockConn,buffer,m,0);
//closesocket
    closesocket(sockConn);
    closesocket(serverSocket);

    return 0;
}

客户端:

#include <iostream>
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define BUF_SIZE 100

int main() { WORD sockVersion = MAKEWORD(2, 2); WSADATA data; if (WSAStartup(sockVersion, &data) != 0) { return 1; } SOCKET clientSocket = socket(AF_INET, SOCK_STREAM,0); if (clientSocket == INVALID_SOCKET){ cout << "Socket error" << endl;} SOCKADDR_IN ListenAddr; ListenAddr.sin_family=AF_INET; ListenAddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");; ListenAddr.sin_port=htons(PORT); //connect int ret=0; ret=connect(clientSocket,(sockaddr*)&ListenAddr, sizeof(struct sockaddr_in)); //send char buffer[BUF_SIZE] = {"569"}; send(clientSocket, buffer, BUF_SIZE, 0); //recv char buffRecv[BUF_SIZE]={0}; recv(clientSocket,buffRecv,BUF_SIZE,0); cout<<"返回数据:"<<buffRecv<<endl; //closesocket closesocket(clientSocket); return 0; }

结果:客户端接收到自己发送给服务器的信息,并打印出来

(待续)


Reference

https://www.cnblogs.com/quehualin/p/9334030.html

https://blog.csdn.net/guothin/article/details/80635400

http://c.biancheng.net/cpp/html/3038.html

[Sign]做不出ctf题的时候很痛苦,你只能眼睁睁看着其他人领先你
原文地址:https://www.cnblogs.com/echoDetected/p/12653768.html