//每个想学socket的,都想了解或实现socket通信是怎样,我原来也是。不过还是一直没做过聊天工具。
//以下简单实现下。用了pthread线程库(学linux下的库挺简单的,书上全介绍了,感觉没windows那么繁琐)
//可以跟上一篇select读写(3)通信
1 #include <iostream>
2 #include <string>
3 using namespace std;
4
5 #include <WinSock2.h>
6 #pragma comment(lib, "ws2_32.lib")
7
8 #include "../tinyhttp/incl/pthread.h"
9 #pragma comment(lib, "../tinyhttp/pthreadVCE2.lib")
10
11 SOCKET initSock();
12 void* run_sock(void *arg);
13 void* run_chat(void *arg);
14
15 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
16 pthread_cond_t done = PTHREAD_COND_INITIALIZER;
17 int g_trdcount = 0;
18 SOCKET g_sock = 0;
19 fd_set g_fdsetw;
20 char sndbuf[1024];
21
22 int main(int argc, char** argv)
23 {
24 g_sock = initSock();
25
26 pthread_t trd;
27 //
28 g_trdcount++;
29 FD_ZERO(&g_fdsetw);
30 pthread_create(&trd, 0, run_chat, 0);
31 //
32 g_trdcount++;
33 pthread_create(&trd, 0, run_sock, 0);
34
35 pthread_mutex_lock(&mutex);
36 while(g_trdcount > 0)
37 {
38 pthread_cond_wait(&done, &mutex);
39 }
40 pthread_mutex_unlock(&mutex);
41
42 return 0;
43 }
44
45 void *run_sock(void *arg)
46 {
47 char buf[1024];
48 //select
49 fd_set fdsetr;
50 FD_ZERO(&fdsetr);
51 FD_SET(g_sock, &fdsetr);
52
53 fd_set fdRead;
54 fd_set fdWrite;
55
56 struct timeval tm = {0, 100*1000};
57 while(true)
58 {
59 fdRead = fdsetr;
60 fdWrite = g_fdsetw;
61
62 int num = select(0, &fdRead, &fdWrite, 0, &tm);
63 if (num > 0)
64 {
65 //recv
66 if(FD_ISSET(g_sock, &fdRead))
67 {
68 int ret = recv(g_sock, buf, sizeof(buf), 0);
69 if (ret > 0)
70 {
71 buf[ret] = '\0';
72 cout<<"recv :"<<buf<<endl;
73 }
74 }
75
76 //write
77 if (FD_ISSET(g_sock, &fdWrite))
78 {
79 int ilen = strlen(sndbuf);
80 if (ilen > 0)
81 {
82 int ret = send(g_sock, sndbuf, ilen, 0);
83 if (ret > 0)
84 {
85 cout<<"send :"<<ret<<endl;
86 }
87 }
88
89 FD_CLR(g_sock, &g_fdsetw);
90 }
91 }
92 }
93
94 pthread_mutex_lock(&mutex);
95 g_trdcount--;
96 if (g_trdcount <= 0)
97 {
98 pthread_cond_signal(&done);
99 }
100 pthread_mutex_unlock(&mutex);
101 return NULL;
102 }
103
104 void* run_chat(void *arg)
105 {
106 string s;
107 while(getline(cin, s))
108 {
109 FD_SET(g_sock, &g_fdsetw);
110 memcpy(sndbuf, s.c_str(), s.length()+1);
111 }
112
113 pthread_mutex_lock(&mutex);
114 while(g_trdcount > 0)
115 {
116 pthread_cond_wait(&done, &mutex);
117 }
118 pthread_mutex_unlock(&mutex);
119
120 return NULL;
121 }
122
123 SOCKET initSock()
124 {
125 //1.
126 WSAData wsa;
127 WSAStartup(MAKEWORD(2,2), &wsa);
128
129 //2.socket
130 SOCKET sk = socket(AF_INET, SOCK_STREAM, 0);
131
132 //3.
133 sockaddr_in addr;
134 addr.sin_family = AF_INET;
135 addr.sin_port = htons(8080);
136 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
137 connect(sk, (sockaddr*)&addr, sizeof(addr));
138
139 return sk;
140 }