写个C语言的Socket博文,运行效果如下:
实现步骤:
1. Server端
1 #include <stdio.h> //用于printf等函数的调用 2 #include <winsock2.h> //Socket的函数调用 3 #pragma comment (lib, "ws2_32") //C语言引用其他类库时,除了.h文件外,还要加入对应的lib文件(这个不同于C#) 4 int main() 5 { 6 WSADATA wsaData; 7 WSAStartup(MAKEWORD(2, 2), &wsaData); 8 9 SOCKET s=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 10 11 sockaddr_in sockaddr; 12 sockaddr.sin_family=PF_INET; 13 sockaddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); //需要绑定到本地的哪个IP地址 14 sockaddr.sin_port=htons(9000); //需要监听的端口 15 bind(s, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR)); //进行绑定动作 16 17 listen(s, 1); //启动监听 18 19 printf("listening on port [%d].\n", 9000); 20 21 while(TRUE) 22 { 23 SOCKADDR clientAddr; 24 int size=sizeof(SOCKADDR); 25 26 SOCKET clientsocket; 27 clientsocket=accept(s, &clientAddr, &size); //阻塞,直到有新tcp客户端连接 28 printf("***SYS*** New client touched.\n"); 29 30 char* msg="Hello, my client.\r\n"; 31 send(clientsocket, msg, strlen(msg)+sizeof(char), NULL); //这里的第三个参数要注意,是加了一个char长度的 32 printf("***SYS*** HELLO.\n"); 33 34 while(TRUE) 35 { 36 char buffer[MAXBYTE]={0}; 37 recv(clientsocket, buffer, MAXBYTE, NULL); //一直接收客户端socket的send操作 38 printf("***Client*** %s\n", buffer); 39 } 40 41 closesocket(clientsocket); //关闭socket 42 } 43 44 closesocket(s); //关闭监听socket 45 46 WSACleanup(); //卸载 47 48 getchar(); 49 50 exit(0); 51 }
由于还在学习中,因此没有实现多线程,因此客户端实际上只能1个,其他的会被挡在外面
关于socket的缓冲区还有点学问,比如最后要\r\n结尾等,都是有原因的,建议看看资料。
2. Client端
1 int main() 2 { 3 Sleep(2000); //沉睡2秒再连接server 4 5 WSADATA wsaData; 6 WSAStartup(MAKEWORD(2, 2), &wsaData); 7 8 SOCKET s=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 9 10 sockaddr_in sockaddr; 11 sockaddr.sin_family=PF_INET; 12 sockaddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); 13 sockaddr.sin_port=htons(9000); 14 15 connect(s, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR)); 16 17 char buffer[MAXBYTE]={0}; 18 recv(s, buffer, MAXBYTE, NULL); 19 printf("***SERVER***%s", buffer); 20 21 while(TRUE) 22 { 23 char* mymsg=new char[100000]; 24 printf("You can chat with server now:\n"); 25 gets(mymsg); 26 send(s, mymsg, strlen(mymsg)+sizeof(char), NULL); 27 /* 28 recv函数中的bufferlength参数是可以固定值的 29 send函数中的bufferlength参数不能固定值,需要看实际长度,并且考虑到'\0'字符串 30 */ 31 } 32 33 closesocket(s); 34 35 WSACleanup(); 36 37 getchar(); 38 39 exit(0); 40 }