0%

socket编程尝试(Windows)

socket编程尝试(Windows)

首先是对于socket这一技术,贴一篇文章

socket技术详解

用一张图概括整个过程(linux下的,与windows不同之处在于函数名和一些细小差别)

image-20220520081743268

针对详细过程,请参阅上述文章,此处不再赘述

我们着重讲编程部分。

首先是客户端

Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
#include <cstdio>
#include <Winsock2.h>
#include <string>


#pragma comment(lib, "ws2_32.lib") //表示链接Ws2_32.lib这个库。

using namespace std;

#define xPort 8000 //端口
#define xIP "127.0.0.1" // ip

int main()
{
const int xBUF_SIZE = 64;
WSADATA wsd; //WSADATA变量
SOCKET xServer; //服务器套接字
SOCKET xClient; //客户端套接字
char input[xBUF_SIZE]; //接受数据缓冲区
char str[xBUF_SIZE]; //返回数据缓冲区
int retVal; //返回值

if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) //初始化
{
cout << "WSAStartup failed!" << endl;
return 1;
}

xClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //创建一个socket
if (INVALID_SOCKET == xClient)
{
cout << "socket failed!" << endl;
WSACleanup();
return -1;
}

struct sockaddr_in sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充
sockAddr.sin_family = PF_INET;
sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
sockAddr.sin_port = htons(8000);

retVal = connect(xClient, (LPSOCKADDR)&sockAddr, sizeof(sockAddr)); //连接
if (SOCKET_ERROR == retVal)
{
cout << "connect failed!" << endl;
closesocket(xClient);
WSACleanup();
return -1;
}
//客户端初始化完成

while (true)
{
memset(input, 0, xBUF_SIZE);
cout << "Input:" ;
scanf("%s",input);
retVal = send(xClient, input, xBUF_SIZE, 0);
recv(xClient, str, xBUF_SIZE, 0);
cout << str << endl;
break;
}

closesocket(xClient);
WSACleanup();

return 0;

}

上述sockaddr_in的结构体定义如下

1
2
3
4
5
6
7
8
9
10
11
struct sockaddr_in {

  short int sin_family; /* 通信类型 */

  unsigned short int sin_port; /* 端口 */

  struct in_addr sin_addr; /* Internet 地址 */

  unsigned char sin_zero[8]; /* 与sockaddr结构的长度相同*/

};

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <iostream>
#include <cstdio>
#include <Winsock2.h>
#include <string>


#pragma comment(lib, "ws2_32.lib")

using namespace std;

#define xPort 8000
#define xIP "127.0.0.1"


int main()
{
const int xBUF_SIZE = 64;
WSADATA wsd; //WSADATA变量
SOCKET xServer; //服务器套接字
SOCKET xClient; //客户端套接字
SOCKADDR_IN xaddrServ;
char string[xBUF_SIZE]; //接受数据缓冲区
char sendinput[xBUF_SIZE]; //返回数据缓冲区
int retVal; //返回值


if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
{
cout << "WSAStartup failed!" << endl;
return 1;
}
//创建一个socket
xServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == xServer)
{
cout << "socket failed" << endl;
WSACleanup();
return -1;
}
//服务器socket地址
xaddrServ.sin_family = AF_INET;
xaddrServ.sin_port = htons(xPort);
xaddrServ.sin_addr.s_addr = INADDR_ANY;

//绑定socket
retVal = bind(xServer, (SOCKADDR*)&xaddrServ, sizeof(SOCKADDR_IN));
if (SOCKET_ERROR == retVal)
{
cout << "bind failed" << endl;
closesocket(xServer);
WSACleanup();
return -1;
}

retVal = listen(xServer, 1);
if (SOCKET_ERROR == retVal)
{
cout << "listen failed" << endl;
closesocket(xServer);
WSACleanup();
return -1;
}

sockaddr_in addrClient;
int addrClientLen = sizeof(addrClient);
xClient = accept(xServer, (sockaddr FAR*) & addrClient, &addrClientLen);//创建一个等待链接的客户端socket
if (INVALID_SOCKET == xClient)
{
cout << "accept failed" << endl;
closesocket(xServer);
WSACleanup();
return -1;
}

//初始化完成

while (true)
{
memset(sendinput, 0, xBUF_SIZE);
recv(xClient,sendinput,xBUF_SIZE,0);
cout << sendinput;
memset(string,0,xBUF_SIZE);
strcpy(string, "good :)");
send(xClient,string,xBUF_SIZE,0);
}

closesocket(xServer);
closesocket(xClient);
WSACleanup();

return 0;

}

原本想在服务端加一个RC4加密的,结果有一些问题,也不太想改,就让客户端输入,服务端返回一个字符串了。

这只是单线程的socket编程。

参考文章

https://www.cnblogs.com/kefeiGame/p/7246942.html

https://www.cnblogs.com/L-hq815/archive/2012/07/09/2583043.html(linux下)

推介结合winapi看

(后续找个时间试试多线程)