//每个想学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 }