一、hello/hi网络程序编程
1、服务端
1 sever.c 2 #include3 #include 4 #include 5 #include<string.h> 6 #pragma warning(disable:4996) 7 #pragma comment(lib,"ws2_32.lib") 8 9 #define USER_ERROR -1 10 11 int main() 12 { 13 char recvData[200]; 14 char sendData[200]; 15 int ret; 16 WSADATA wsaData; 17 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 18 { 19 printf("Failed to load Winsock.\n"); 20 return USER_ERROR; 21 } 22 23 SOCKET socket_of_server; 24 SOCKET socket_of_client; 25 socket_of_server = socket(AF_INET, SOCK_STREAM, 0); 26 if (socket_of_server == INVALID_SOCKET) 27 { 28 printf("socket() Failed:%d\n", WSAGetLastError()); 29 return USER_ERROR; 30 } 31 32 struct sockaddr_in s_sin; 33 s_sin.sin_family = AF_INET; 34 s_sin.sin_port = htons(6666); 35 s_sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY); 36 if (bind(socket_of_server, (LPSOCKADDR)&s_sin, sizeof(s_sin)) == SOCKET_ERROR) 37 { 38 printf("blind() Failed:%d\n", WSAGetLastError()); 39 return USER_ERROR; 40 } 41 if (listen(socket_of_server, 5) == SOCKET_ERROR) 42 { 43 printf("listen() Failed:%d\n", WSAGetLastError()); 44 return USER_ERROR; 45 } 46 struct sockaddr_in c_sin; 47 int c_sin_len = sizeof(c_sin); 48 while (1) 49 { 50 printf("waiting for connect\n"); 51 socket_of_client = accept(socket_of_server, (SOCKADDR*)&c_sin, &c_sin_len); 52 if (socket_of_client == INVALID_SOCKET) 53 printf("accept() Failed:%d\n", WSAGetLastError()); 54 else 55 { 56 printf("接收到一个连接:%s\r\n", inet_ntoa(c_sin.sin_addr)); 57 while (1) 58 { 59 printf("读取消息:"); 60 recvData[0] = '\0'; 61 ret = recv(socket_of_client, recvData, 200, 0); 62 if (ret < 0) 63 { 64 printf("something wrong\n"); 65 continue; 66 } 67 recvData[ret] = '\0'; 68 if (strcmp(recvData, "quit") == 0) 69 break; 70 printf("%s\n", recvData); 71 printf("发送消息:"); 72 scanf("%s", sendData); 73 printf("\n"); 74 send(socket_of_client, sendData, strlen(sendData), 0); 75 if (strcmp("quit", sendData) == 0) 76 break; 77 } 78 } 79 80 } 81 82 closesocket(socket_of_server); 83 WSACleanup(); 84 return 0; 85 }
2、客户端
1 client.c 2 #include3 #include 4 #include 5 #include <string.h> 6 #include 7 #pragma comment(lib,"ws2_32.lib") 8 #pragma warning(disable:4996) 9 10 #define USER_ERROR -1 11 12 int main() 13 { 14 char recvData[200]; 15 char sendData[200]; 16 int ret; 17 18 19 WSADATA wsaData; 20 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 21 { 22 printf("Failed to load Winsock.\n"); 23 return USER_ERROR; 24 } 25 26 SOCKET socket_client = socket(AF_INET, SOCK_STREAM, 0); 27 if (socket_client == INVALID_SOCKET) 28 { 29 printf(" Failed socket() \n"); 30 return 0; 31 } 32 33 struct sockaddr_in server_in; 34 server_in.sin_family = AF_INET; 35 server_in.sin_port = htons(6666); 36 server_in.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); 37 38 if (connect(socket_client, (struct sockaddr*) & server_in, sizeof(server_in)) == -1) 39 { 40 printf(" Failed connect() \n"); 41 return 0; 42 } 43 else 44 { 45 printf("connect %s.%d\n", inet_ntoa(server_in.sin_addr), server_in.sin_port); 46 while (1) 47 { 48 printf("发送消息:"); 49 scanf("%s", sendData); 50 printf("\n"); 51 send(socket_client, sendData, strlen(sendData), 0); 52 if (strcmp(sendData, "quit") == 0) 53 break; 54 printf("读取消息:"); 55 recvData[0] = '\0'; 56 ret = recv(socket_client, recvData, 200, 0); 57 recvData[ret] = '\0'; 58 printf("%s\n", recvData); 59 } 60 61 } 62 closesocket(socket_client); 63 WSACleanup(); 64 return 0; 65 }
3、示例图
二、WinSocket分析
1、WSAStartup()——初始化Socket
定义函数为int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData ),为了在应用程序当中调用任何一个Winsock API函数,首先第一件事情就是必须通过WSAStartup函数完成对Winsock服务的初始化,因此需要调用WSAStartup函数。使用Socket的程序在使用Socket之前必须调用WSAStartup函数。
2、socket()——建立一个Socket通信
定义函数为int socket(int domain,int type,int protocol),socket()用来建立一个新的socket,也就是向系统注册,通知系统建立一通信端口,参数domain 指定使用何种的地址类型,完整的定义在/usr/include/bits/socket.h 内。
3、listen()——等待连接
定义函数为int listen(int s,int backlog),listen()用来等待参数s 的socket连线。Listen()并未开始接收连线,只是设置socket为listen模式,真正接收client端连线的是accept()。通常listen()会在socket(),bind()之后调用,接着才调用accept()。
4、connect()——建立Socket连接
定义函数为int connect (int sockfd,struct sockaddr * serv_addr,int addrlen),connect()用来将参数sockfd 的socket 连至参数serv_addr 指定的网络地址。结构sockaddr请参考bind()。参数addrlen为sockaddr的结构长度。
5、bind()——对Socket定位
定义函数为int bind(int sockfd,struct sockaddr * my_addr,int addrlen),bind()用来设置给参数sockfd的socket一个名称。此名称由参数my_addr指向一sockaddr结构,对于不同的socket domain定义了一个通用的数据结构。
6、accept()——接受Socket连线
定义函数为int accept(int s,struct sockaddr * addr,int * addrlen),
accept()用来接受参数s的socket连线。参数s的socket必需先经bind()、listen()函数处理过,当有连线进来时accept()会返回一个新的socket处理代码,往后的数据传送与读取就是经由新的socket处理,而原来参数s的socket能继续使用accept()来接受新的连线要求。连线成功时,参数addr所指的结构会被系统填入远程主机的地址数据。
7、recv()——经Socket接受数据
定义函数为int recv(int s,void *buf, int len, unsigned int flags),recv()用来接收远端主机经指定的socket传来的数据,并把数据存到由参数buf 指向的内存空间,参数len为可接收数据的最大长度。
8、send()——经Socket发送数据
定义函数为int send(int s,const void * msg,int len,unsigned int falgs),send()用来将数据由指定的socket 传给对方主机。参数s为已建立好连接的socket。参数msg指向欲连线的数据内容,参数len则为数据长度。