实现简单的Socket通信
服务端代码(Server)
复制代码
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#include <stdio.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") #define PORT 9999 int main() { WSADATA WSAData; SOCKET sock, msgsock; struct sockaddr_in ServerAddr; if (WSAStartup(MAKEWORD(2, 0), &WSAData) != SOCKET_ERROR) { ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(PORT); ServerAddr.sin_addr.s_addr = INADDR_ANY; sock = socket(AF_INET, SOCK_STREAM, 0); int BindRet = bind(sock, (LPSOCKADDR)&ServerAddr, sizeof(ServerAddr)); int LinsRet = listen(sock, 10); printf("------------------------------------------------------------------------------------------n"); printf("绑定状态: %dt 侦听状态: %dt 绑定端口: %dn", BindRet, LinsRet, ntohs(ServerAddr.sin_port)); printf("------------------------------------------------------------------------------------------n"); } while (1) { char buf[1024]; msgsock = accept(sock, (LPSOCKADDR)0, (int *)0); memset(buf, 0, sizeof(buf)); recv(msgsock, buf, 1024, 0); printf("客户IP: %st 端口:%dt 数据:%sn", inet_ntoa(ServerAddr.sin_addr), htons(ServerAddr.sin_port),buf); if (!strcmp(buf, "Success")) { printf("客户端已就绪...n"); } closesocket(msgsock); } closesocket(sock); WSACleanup(); return 0; }
客户端代码(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#include <winsock2.h> #include <stdio.h> #pragma comment(lib,"ws2_32.lib") #define IP "127.0.0.1" #define PORT 9999 //#ifdef _MSC_VER //#pragma comment( linker, "/subsystem:"windows" /entry:"mainCRTStartup"" ) //#endif int main() { while (1) { WSADATA WSAData; SOCKET sock; struct sockaddr_in ClientAddr; if (WSAStartup(MAKEWORD(2, 0), &WSAData) != SOCKET_ERROR) { ClientAddr.sin_family = AF_INET; //指Internet域 ClientAddr.sin_port = htons(PORT); //指定服务端所预留的端口 ClientAddr.sin_addr.s_addr = inet_addr(IP); //指定服务端所绑定的IP地址 sock = socket(AF_INET, SOCK_STREAM, 0); int Ret = connect(sock, (LPSOCKADDR)&ClientAddr, sizeof(ClientAddr)); if (Ret == 0) { char Status[] = "Success"; int ServerRet = send(sock, Status, sizeof(Status), 0); if (ServerRet != 0) { printf("发送给服务器Success状态成功..n"); } } } closesocket(sock); WSACleanup(); Sleep(5000); } return 0; }
实现Socket单工通信案例
服务端代码(Server)
复制代码
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#include <stdio.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") //把ws2_32.lib加到Link页的连接库 #define PORT 15001 //通信的端口(指服务器端) #define ERROR 0 #define BUFFER_SIZE 1024 //注意:此Server端数据接收缓冲区 >= Client端数据发送缓冲区 ,否则造成缓冲区溢出 /* 服务端原理: 1、服务器进程创建套接字 2、将本地地址绑定到所创建的套接字上,以三元组{<通信协议>,<IP地址>,<端口号>}在网络上标识该套接字 3、将套接字置入监听模式,并准备接受连接请求 */ int main() { WSADATA WSAData; if(WSAStartup(MAKEWORD(2,0),&WSAData)==SOCKET_ERROR) //启动winsock ,WSAStartup()函数对Winsock DLL进行初始化 { printf("Socket initialize fail!n"); exit(1); } SOCKET sock; //服务进程创建套接字句柄(用于监听) if((sock=socket(AF_INET,SOCK_STREAM,0))==ERROR) //调用socket()函数创建一个流套接字,参数(网络地址类型,套接字类型,网络协议) { printf("Socket create!n"); WSACleanup(); exit(1); } struct sockaddr_in ServerAddr; //sockaddr_in结构用来标识TCP/IP协议下的地址,可强制转换为sockaddr结构 ServerAddr.sin_family=AF_INET; //sin_family字段必须设为AF_INET,表示该Socket处于Internet域 ServerAddr.sin_port=htons(PORT); //sin_port字段用于指定服务端口,注意避免冲突 ServerAddr.sin_addr.s_addr=INADDR_ANY; //sin_addr字段用于把一个IP地址保存为一个4字节的数,无符号长整型,根据不同用法还可表示本地或远程IP地址 if(bind(sock,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr))==SOCKET_ERROR) //调用bind()函数将本地地址绑定到所创建的套接字上,以在网络上标识该套接字 { printf("Bind fail!n"); closesocket(sock); WSACleanup(); exit(1); } printf("Server Socket Port:%dn",ntohs(ServerAddr.sin_port)); if(listen(sock,10)==SOCKET_ERROR) //调用listen()函数将套接字置入监听模式并准备接受连接请求,参数(已捆绑未连接的套接字描述字,正在等待连接的最大队列长度) { printf("Listen fail!n"); closesocket(sock); WSACleanup(); exit(1); } SOCKET msgsock; //创建一个新的套接字(用于接收accept函数的返回值,即表示已经接受的那个客户端的连接,进而接收Client发来的数据) char buf[BUFFER_SIZE]; //数据接收缓冲区 while(1) { if((msgsock=accept(sock,(LPSOCKADDR)0,(int *)0))==INVALID_SOCKET) //进入监听状态后,调用accept()函数接收客户端的连接请求,并把连接传给msgsock套接字,原sock套接字继续监听其他客户机连接请求 { printf("Accept fail!n"); continue; } memset(buf,0,sizeof(buf)); //初始化数据接收缓冲区 recv(msgsock,buf,BUFFER_SIZE,0); //接收客户端发送过来的数据 if(buf[0]=='e' && buf[1]=='x' && buf[2]=='i' && buf[3]=='t') //"exit"命令,退出程序 { printf("The End.n"); break; } printf("C:\Socket\Server>%s",buf); closesocket(msgsock); } closesocket(sock); //关闭套接字 WSACleanup(); //终止对Winsock DLL的使用,并释放资源 return 0; }
客户端代码(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#include <winsock2.h> #include <stdio.h> #pragma comment(lib,"ws2_32.lib") //把ws2_32.lib加到Link页的连接库 //#define IP "172.18.68.243" //在两台计算机上测试,IP为Server端的IP地址 #define IP "127.0.0.1" //在一台计算机上测试,IP为本地回送地址 #define PORT 15001 //注意:客户端设置通信的端口 = 服务端的端口 #define BUFFER_SIZE 1024 //数据发送缓冲区大小 int main() { char buf[BUFFER_SIZE]; //buf数组存放客户端发送的消息 int inputLen; //用于输入字符自增变量 while(1) { printf("C:\Socket\Client>"); inputLen=0; memset(buf,0,sizeof(buf)); while((buf[inputLen++]=getchar())!='n') //输入以回车键为结束标识 { ; } if(buf[0]=='e' && buf[1]=='x' && buf[2]=='i' && buf[3]=='t') { printf("The End.n"); break; } WSADATA WSAData; if(WSAStartup(MAKEWORD(2,0),&WSAData)==SOCKET_ERROR) //WSAStartup()函数对Winsock DLL进行初始化 { printf("Socket initialize fail!n"); continue; } SOCKET sock; //客户端进程创建套接字 if((sock=socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR) //创建流套接字(与服务端保持一致) { printf("Socket create fail!n"); WSACleanup(); continue; } struct sockaddr_in ClientAddr; //sockaddr_in结构用来标识TCP/IP协议下的地址,可强制转换为sockaddr结构 ClientAddr.sin_family=AF_INET; //指Internet域 ClientAddr.sin_port=htons(PORT); //指定服务端所预留的端口 ClientAddr.sin_addr.s_addr=inet_addr(IP); //指定服务端所绑定的IP地址 if(connect(sock,(LPSOCKADDR)&ClientAddr,sizeof(ClientAddr))==SOCKET_ERROR) //调用connect()函数,向服务器进程发出连接请求 { printf("Connect fail!n"); closesocket(sock); WSACleanup(); continue; } send(sock,buf,BUFFER_SIZE,0); //向服务器发送数据 closesocket(sock); //关闭套接字 WSACleanup(); //终止对Winsock DLL的使用,并释放资源,以备下一次使用 } return 0; }
实现Socket双工通信案例
服务端代码(Server)
复制代码
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120#include <stdio.h> #include <Winsock2.h> //Socket的函数调用 #include <windows.h> #define BUF_SIZE 6400 // 缓冲区大小 #pragma comment (lib, "ws2_32") // 使用WINSOCK2.H时,则需要库文件WS2_32.LIB DWORD WINAPI Rcv(LPVOID lpParam) { SOCKET sClient = *(SOCKET*)lpParam; int retVal; char bufRecv[BUF_SIZE]; memset(bufRecv, 0, sizeof(bufRecv)); while (1) { retVal = recv(sClient, bufRecv, BUF_SIZE, 0); if (retVal == SOCKET_ERROR) { printf("recive faild!n"); break; } else { printf("收到客户端消息:%sn", bufRecv); } } return 0; } DWORD WINAPI Snd(LPVOID lpParam) { SOCKET sClient = *(SOCKET*)lpParam; int retVal; char bufSend[BUF_SIZE]; memset(bufSend, 0, sizeof(bufSend)); while (1) { gets(bufSend); retVal = send(sClient, bufSend, strlen(bufSend) + sizeof(char), 0); if (retVal == SOCKET_ERROR) { printf("send faild!n"); break; } } return 0; } int main(int argc, char* argv[]) { // 初始化套接字动态库 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { printf("winsock load faild!n"); return 1; } // 创建服务段套接字 SOCKET sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sServer == INVALID_SOCKET) { printf("socket faild!n"); WSACleanup(); return -1; } // 服务端地址 sockaddr_in addrServ; addrServ.sin_family = AF_INET; addrServ.sin_port = htons(9999); addrServ.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定套接字 if (bind(sServer, (const struct sockaddr*)&addrServ, sizeof(addrServ)) == SOCKET_ERROR) { printf("bind faild!n"); closesocket(sServer); WSACleanup(); return -1; } printf("Server is On IP:[%s],port:[%d]n", inet_ntoa(addrServ.sin_addr), ntohs(addrServ.sin_port)); // 监听套接字 数字表示最多能监听客户个数 if (listen(sServer, 5) == SOCKET_ERROR) { printf("listen faild!n"); closesocket(sServer); WSACleanup(); return -1; } SOCKET sClient; // 客户端套接字 sockaddr_in addrClient; int addrClientLen = sizeof(addrClient); sClient = accept(sServer, (sockaddr FAR*)&addrClient, &addrClientLen); if (sClient == INVALID_SOCKET) { printf("accept faild!n"); closesocket(sServer); WSACleanup(); return -1; } printf("accepted client IP:[%s],port:[%d]n", inet_ntoa(addrClient.sin_addr), ntohs(addrClient.sin_port)); HANDLE hThread1, hThread2; DWORD dwThreadId1, dwThreadId2; hThread1 = ::CreateThread(NULL, NULL, Snd, (LPVOID*)&sClient, 0, &dwThreadId1); hThread2 = ::CreateThread(NULL, NULL, Rcv, (LPVOID*)&sClient, 0, &dwThreadId2); ::WaitForSingleObject(hThread1, INFINITE); ::WaitForSingleObject(hThread2, INFINITE); ::CloseHandle(hThread1); ::CloseHandle(hThread2); closesocket(sClient); WSACleanup(); // 资源释放 return 0; }
客户端代码(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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93#include <stdio.h> #include <Winsock2.h> //Socket的函数调用 #include <windows.h> #define BUF_SIZE 6400 #pragma comment (lib, "ws2_32") // 使用WINSOCK2.H时,则需要库文件WS2_32.LIB DWORD WINAPI Rcv(LPVOID lpParam) { SOCKET sHost = *(SOCKET*)lpParam; int retVal; char bufRecv[BUF_SIZE]; memset(bufRecv, 0, sizeof(bufRecv)); while (1) { retVal = recv(sHost, bufRecv, BUF_SIZE, 0); if (retVal == SOCKET_ERROR) { printf("recive faild!n"); break; } else { printf("收到服务器消息:%sn", bufRecv); } } return 0; } DWORD WINAPI Snd(LPVOID lpParam) { SOCKET sHost = *(SOCKET*)lpParam; int retVal; char bufSend[BUF_SIZE]; memset(bufSend, 0, sizeof(bufSend)); while (1) { gets(bufSend); retVal = send(sHost, bufSend, strlen(bufSend) + sizeof(char), 0); if (retVal == SOCKET_ERROR) { printf("send faild!n"); break; } } return 0; } int main(int argc, char* argv[]) { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { printf("Winsock load faild!n"); return 1; } // 服务器套接字 SOCKET sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sHost == INVALID_SOCKET) { printf("socket faild!n"); WSACleanup(); return -1; } SOCKADDR_IN servAddr; servAddr.sin_family = AF_INET; // 注意 当把客户端程序发到别人的电脑时 此处IP需改为服务器所在电脑的IP servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); servAddr.sin_port = htons(9999); // 连接服务器 if (connect(sHost, (LPSOCKADDR)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) { printf("connect faild!n"); closesocket(sHost); WSACleanup(); return -1; } printf("连接到服务器 IP:[%s],port:[%d]n", inet_ntoa(servAddr.sin_addr), ntohs(servAddr.sin_port)); HANDLE hThread1, hThread2; DWORD dwThreadId1, dwThreadId2; hThread1 = ::CreateThread(NULL, NULL, Snd, (LPVOID)&sHost, 0, &dwThreadId1); hThread2 = ::CreateThread(NULL, NULL, Rcv, (LPVOID)&sHost, 0, &dwThreadId2); ::WaitForSingleObject(hThread1, INFINITE); ::WaitForSingleObject(hThread2, INFINITE); ::CloseHandle(hThread1); ::CloseHandle(hThread2); closesocket(sHost); WSACleanup(); return 0; }
实现文件传输
复制代码
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109#include <stdio.h> #include <stdlib.h> #include <string.h> #include <WinSock2.h> #define PORT 8087 #define SERVER_IP "127.0.0.1" #define BUFFER_SIZE 1024 #define FILE_NAME_MAX_SIZE 512 #pragma comment(lib, "WS2_32") int main() { // 声明并初始化一个服务端(本地)的地址结构 sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.S_un.S_addr = INADDR_ANY; server_addr.sin_port = htons(PORT); // 初始化socket dll WSADATA wsaData; WORD socketVersion = MAKEWORD(2, 0); if (WSAStartup(socketVersion, &wsaData) != 0) { printf("Init socket dll error!"); exit(1); } // 创建socket SOCKET m_Socket = socket(AF_INET, SOCK_STREAM, 0); if (SOCKET_ERROR == m_Socket) { printf("Create Socket Error!"); exit(1); } //绑定socket和服务端(本地)地址 if (SOCKET_ERROR == bind(m_Socket, (LPSOCKADDR)&server_addr, sizeof(server_addr))) { printf("Server Bind Failed: %d", WSAGetLastError()); exit(1); } //监听 if (SOCKET_ERROR == listen(m_Socket, 10)) { printf("Server Listen Failed: %d", WSAGetLastError()); exit(1); } while (1) { printf("Listening To Client...n"); sockaddr_in client_addr; int client_addr_len = sizeof(client_addr); SOCKET m_New_Socket = accept(m_Socket, (sockaddr *)&client_addr, &client_addr_len); if (SOCKET_ERROR == m_New_Socket) { printf("Server Accept Failed: %d", WSAGetLastError()); break; } char buffer[BUFFER_SIZE]; memset(buffer, 0, BUFFER_SIZE); if (recv(m_New_Socket, buffer, BUFFER_SIZE, 0) < 0) { printf("Server Receive Data Failed!"); break; } char file_name[FILE_NAME_MAX_SIZE + 1]; memset(file_name, 0, FILE_NAME_MAX_SIZE + 1); strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buffer)); printf("%sn", file_name); FILE * fp = fopen(file_name, "rb"); //windows下是"rb",表示打开一个只读的二进制文件 if (NULL == fp) { printf("File: %s Not Foundn", file_name); } else { memset(buffer, 0, BUFFER_SIZE); int length = 0; while ((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0) { if (send(m_New_Socket, buffer, length, 0) < 0) { printf("Send File: %s Failedn", file_name); break; } memset(buffer, 0, BUFFER_SIZE); } fclose(fp); printf("File: %s Transfer Successful!n", file_name); } closesocket(m_New_Socket); } closesocket(m_Socket); //释放winsock库 WSACleanup(); return 0; }
复制代码
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
94
95
96
97
98
99
100
101/************************************************************************* > File Name: Win_Client.c > Author: SongLee ************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <WinSock2.h> #define PORT 8087 #define SERVER_IP "127.0.0.1" #define BUFFER_SIZE 1024 #define FILE_NAME_MAX_SIZE 512 #pragma comment(lib, "WS2_32") int main() { // 初始化socket dll WSADATA wsaData; WORD socketVersion = MAKEWORD(2, 0); if (WSAStartup(socketVersion, &wsaData) != 0) { printf("Init socket dll error!"); exit(1); } //创建socket SOCKET c_Socket = socket(AF_INET, SOCK_STREAM, 0); if (SOCKET_ERROR == c_Socket) { printf("Create Socket Error!"); system("pause"); exit(1); } //指定服务端的地址 sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.S_un.S_addr = inet_addr(SERVER_IP); server_addr.sin_port = htons(PORT); if (SOCKET_ERROR == connect(c_Socket, (LPSOCKADDR)&server_addr, sizeof(server_addr))) { printf("Can Not Connect To Server IP!n"); system("pause"); exit(1); } //输入文件名 char file_name[FILE_NAME_MAX_SIZE + 1]; memset(file_name, 0, FILE_NAME_MAX_SIZE + 1); printf("Please Input File Name On Server: "); scanf("%s", &file_name); char buffer[BUFFER_SIZE]; memset(buffer, 0, BUFFER_SIZE); strncpy(buffer, file_name, strlen(file_name)>BUFFER_SIZE ? BUFFER_SIZE : strlen(file_name)); //向服务器发送文件名 if (send(c_Socket, buffer, BUFFER_SIZE, 0) < 0) { printf("Send File Name Failedn"); system("pause"); exit(1); } //打开文件,准备写入 FILE * fp = fopen(file_name, "wb"); //windows下是"wb",表示打开一个只写的二进制文件 if (NULL == fp) { printf("File: %s Can Not Open To Writen", file_name); system("pause"); exit(1); } else { memset(buffer, 0, BUFFER_SIZE); int length = 0; while ((length = recv(c_Socket, buffer, BUFFER_SIZE, 0)) > 0) { if (fwrite(buffer, sizeof(char), length, fp) < length) { printf("File: %s Write Failedn", file_name); break; } memset(buffer, 0, BUFFER_SIZE); } printf("Receive File: %s From Server Successful!n", file_name); } fclose(fp); closesocket(c_Socket); //释放winsock库 WSACleanup(); system("pause"); return 0; }
使用select
复制代码
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166#include<stdlib.h> #include<WINSOCK2.H> #include <windows.h> #include <process.h> #include<iostream> #include<string> using namespace std; #define BUF_SIZE 64 #pragma comment(lib,"WS2_32.lib") void recv(PVOID pt) { SOCKET sHost = *((SOCKET *)pt); while (true) { char buf[BUF_SIZE];//清空接收数据的缓冲区 memset(buf, 0, BUF_SIZE); int retVal = recv(sHost, buf, sizeof(buf), 0); if (SOCKET_ERROR == retVal) { int err = WSAGetLastError(); //无法立即完成非阻塞Socket上的操作 if (err == WSAEWOULDBLOCK) { Sleep(1000); printf("nwaiting reply!"); continue; } else if (err == WSAETIMEDOUT || err == WSAENETDOWN || err == WSAECONNRESET)//已建立连接 { printf("nrecv failed!"); closesocket(sHost); WSACleanup(); return; } } Sleep(100); printf("n%s", buf); //break; } } int main() { WSADATA wsd; SOCKET sHost; SOCKADDR_IN servAddr;//服务器地址 int retVal;//调用Socket函数的返回值 char buf[BUF_SIZE]; //初始化Socket环境 if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) { printf("WSAStartup failed!n"); return -1; } sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //设置服务器Socket地址 servAddr.sin_family = AF_INET; servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //在实际应用中,建议将服务器的IP地址和端口号保存在配置文件中 servAddr.sin_port = htons(6000); //计算地址的长度 int sServerAddlen = sizeof(servAddr); //调用ioctlsocket()将其设置为非阻塞模式 int iMode = 1; retVal = ioctlsocket(sHost, FIONBIO, (u_long FAR*)&iMode); if (retVal == SOCKET_ERROR) { printf("ioctlsocket failed!"); WSACleanup(); return -1; } //循环等待 while (true) { //连接到服务器 retVal = connect(sHost, (LPSOCKADDR)&servAddr, sizeof(servAddr)); if (SOCKET_ERROR == retVal) { int err = WSAGetLastError(); //无法立即完成非阻塞Socket上的操作 if (err == WSAEWOULDBLOCK || err == WSAEINVAL) { Sleep(1); printf("check connect!n"); continue; } else if (err == WSAEISCONN)//已建立连接 { break; } else { printf("connection failed!n"); closesocket(sHost); WSACleanup(); return -1; } } } unsigned long threadId = _beginthread(recv, 0, &sHost);//启动一个线程接收数据的线程 while (true) { //向服务器发送字符串,并显示反馈信息 printf("input a string to send:n"); std::string str; //接收输入的数据 std::cin >> str; //将用户输入的数据复制到buf中 ZeroMemory(buf, BUF_SIZE); strcpy(buf, str.c_str()); if (strcmp(buf, "quit") == 0) { printf("quit!n"); break; } while (true) { retVal = send(sHost, buf, strlen(buf), 0); if (SOCKET_ERROR == retVal) { int err = WSAGetLastError(); if (err == WSAEWOULDBLOCK) { //无法立即完成非阻塞Socket上的操作 Sleep(5); continue; } else { printf("send failed!n"); closesocket(sHost); WSACleanup(); return -1; } } break; } } return 0; }
复制代码
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150#include <WinSock2.h> #include <Windows.h> #include <MSWSock.h> #include <stdio.h> #include <map> using namespace std; #pragma comment(lib,"Ws2_32.lib") #pragma comment(lib,"Mswsock.lib") int main() { WSAData wsaData; if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData)) { printf("初始化失败!%dn", WSAGetLastError()); Sleep(5000); return -1; } USHORT nport = 6000; SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); u_long ul = 1; ioctlsocket(sListen, FIONBIO, &ul); sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(nport); sin.sin_addr.S_un.S_addr = ADDR_ANY; if (SOCKET_ERROR == bind(sListen, (sockaddr*)&sin, sizeof(sin))) { printf("bind failed!%dn", WSAGetLastError()); Sleep(5000); return -1; } listen(sListen, 5); //1)初始化一个套接字集合fdSocket,并将监听套接字放入 fd_set socketSet; FD_ZERO(&socketSet); FD_SET(sListen, &socketSet); TIMEVAL time = { 1, 0 }; char buf[4096]; fd_set readSet; FD_ZERO(&readSet); fd_set writeSet; FD_ZERO(&readSet); while (true) { //2)将fdSocket的一个拷贝fdRead传给select函数 readSet = socketSet; writeSet = socketSet; //同时检查套接字的可读可写性。 int nRetAll = select(0, &readSet, &writeSet, NULL, NULL/*&time*/);//若不设置超时则select为阻塞 if (nRetAll >0) //-1 { //是否存在客户端的连接请求。 if (FD_ISSET(sListen, &readSet))//在readset中会返回已经调用过listen的套接字。 { if (socketSet.fd_count < FD_SETSIZE) { sockaddr_in addrRemote; int nAddrLen = sizeof(addrRemote); SOCKET sClient = accept(sListen, (sockaddr*)&addrRemote, &nAddrLen); if (sClient != INVALID_SOCKET) { FD_SET(sClient, &socketSet); printf("n接收到连接:(%s)", inet_ntoa(addrRemote.sin_addr)); } } else { printf("连接数量已达上限!n"); continue; } } for (int i = 0; i<socketSet.fd_count; i++) { if (FD_ISSET(socketSet.fd_array[i], &readSet)) { //调用recv,接收数据。 int nRecv = recv(socketSet.fd_array[i], buf, 4096, 0); if (nRecv > 0) { buf[nRecv] = 0; printf("nrecv %d : %s", socketSet.fd_array[i], buf); } } if (FD_ISSET(socketSet.fd_array[i], &writeSet)) { //调用send,发送数据。 char buf[] = "hello!"; int nRet = send(socketSet.fd_array[i], buf, strlen(buf) + 1, 0); if (nRet <= 0) { if (GetLastError() == WSAEWOULDBLOCK) { //do nothing } else { closesocket(socketSet.fd_array[i]); FD_CLR(socketSet.fd_array[i], &socketSet); } } else { printf("nsend hello!"); } } } } else if (nRetAll == 0) { printf("time out!n"); } else { printf("select error!%dn", WSAGetLastError()); Sleep(5000); break; } Sleep(1000); } closesocket(sListen); WSACleanup(); }
代码来源于网络,你可以随意转载,仅用于收藏!
最后
以上就是真实鸡最近收集整理的关于C/C++ 创建Socket实现双工通信的全部内容,更多相关C/C++内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复