30网络通信之多线程
使用原始的Socket模式,会发生阻塞问题,只能收一条消息再发一条消息。无法做到发送多次消息。
在服务器端创建多线程,每当accept()接受到一个客户端时,启动一条线程单独去处理。
代码:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<unistd.h> #include<pthread.h> #define SRV_PORT 0xabcd #define CLT_PORT 0xaaaa void *Comm_thread(void *param) { int fd = *(int*)param; int iRet; char szBuf[1024]; char szMsg[] = "I Received!"; while(1) { memset(szBuf, 0, 1024); iRet = read(fd, szBuf, 1024); if (iRet < 0) { perror("Recv failed!"); break; } if (iRet == 0) { printf("Disconnect!\n"); break; } else { printf("Recv:%s\n", szBuf); //write(fd, szMsg, sizeof(szMsg)); } } close(fd); return NULL; } void Tcp_server() { int fd; int iRet; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); fd = socket(PF_INET, SOCK_STREAM, 0);//IPPROTO_IP if (fd < 0) { perror("Socket failed!"); return; } addr.sin_family = AF_INET;//use IPV4 address addr.sin_port = htons(SRV_PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY=0L; iRet = bind(fd, (struct sockaddr*)&addr, addrlen); if (iRet) { perror("Bind failed!"); close(fd); return; } iRet = listen(fd, 10); if (iRet) { perror("Listen failed!"); close(fd); return; } int clientfd; struct sockaddr_in srcaddr; char szTip[] = "Welcome!"; //char szBuf[1024]={}; while(1) { clientfd = accept(fd, (struct sockaddr*)&srcaddr, &addrlen); if (clientfd < 0) { perror("Accept failed!"); break; } printf("Connect form %s[%d]\n", inet_ntoa(srcaddr.sin_addr), ntohs(srcaddr.sin_port)); //send(clientfd, szTip, strlen(szTip), 0); write(clientfd, szTip, strlen(szTip)); //send data to client pthread_t tid; pthread_create(&tid, NULL, Comm_thread, (void*)&clientfd); } close(fd); return ; } void Tcp_client() { char szDestIp[16]; int port; fprintf(stderr, "Connect to:"); scanf("%s%d", szDestIp, &port); int fd; int iRet; struct sockaddr_in srvaddr; socklen_t addrlen = sizeof(srvaddr); fd = socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { perror("Socket failed!"); return; } srvaddr.sin_family = AF_INET; srvaddr.sin_port = htons((short)port); srvaddr.sin_addr.s_addr = inet_addr(szDestIp); iRet = connect(fd, (struct sockaddr*)&srvaddr, addrlen); if (iRet) { perror("Connect failed!"); return; } char szBuf[1024]; char szMsg[100]; while(1) { memset(szBuf, 0, 1024); iRet = read(fd, szBuf, 1024);//receive message if (iRet < 0) { perror("Read failed!"); break; } if (iRet == 0) { printf("Server disconnected\n"); } printf("Recv: %s\n", szBuf); fprintf(stderr, "Send:"); memset(szMsg, 0, 100); read(STDIN_FILENO, szMsg, 100);//get message write(fd, szMsg, strlen(szMsg)); //send message } } int main(int argc, char** argv) { if (argc!=2 || (strcmp(argv[1], "s") && strcmp(argv[1], "c") ) ) { printf("Usage: %s [ c | s ]\n", argv[0]); printf("\t c : For start tcp client\n"); printf("\t s : For start tcp server\n"); return 0; } if (argv[1][0] == 's') { Tcp_server(); } else if (argv[1][0] == 'c') { Tcp_client(); } return 0; }