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
[Sign]做不出ctf题的时候很痛苦,你只能眼睁睁看着其他人领先你