- server.c:
#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include <assert.h> #include <stdio.h> #include <string.h> #include <errno.h> int main(int argc,char* argv[]) { printf("server start up\n"); if(argc <= 3) { printf("usage:%s ip port backlog\n",basename(argv[0])); return 1; } //IP地址 const char* ip = argv[1]; //端口号 int port = atoi(argv[2]); //内核监听队列的最大长度(完全连接的socket) int backlog = atoi(argv[3]); //创建socket (TIP/IP协议族,流式socket) int server_sockfd = socket(PF_INET,SOCK_STREAM,0); //TCP/IP协议族的socket地址结构体 struct sockaddr_in server_addr; bzero(&server_addr,sizeof(server_addr)); server_addr.sin_family = AF_INET; //TCP/IPv4的地址族 inet_pton(AF_INET,ip,&server_addr.sin_addr); //将IP地址字符串转换为二进制的整数并赋给addr.sin_server_addr server_addr.sin_port = htons(port); //端口,host to net,将主机字节序(小端)转换为网络字节序(大端) //将文件描述符sock和socket地址关联,仅服务端需要,客户端自动绑定地址 //注意需要强制转换为 struct sockaddr* int ret = bind(server_sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr)); assert(ret != -1); //监听 ret = listen(server_sockfd,backlog); assert(ret != -1); //等待客户端做些连接等相关工作 sleep(5); //客户端地址信息 struct sockaddr_in client_addr; socklen_t client_addr_addrlength = sizeof(client_addr); //接受连接,并将被接受的远端sock地址信息保存在第二个参数中 int client_addr_sockfd = accept(server_sockfd,(struct sockaddr*)&client_addr,&client_addr_addrlength); if(client_addr_sockfd < 0) { printf("errno is:%d\n",errno); return -1; } else { //inet_ntoa(struct addr_in) 将IP地址转换为字符串并返回 //只是从监听队列中取出连接,即使客户端已经断开网络连接也会accept成功 printf("accept client_addr %s\n",inet_ntoa(client_addr.sin_addr)); } int len; char buf[128]; strcpy(buf,"Welcome to my server\n"); //send: TCP数据发送接口 len = send(client_addr_sockfd,buf,strlen(buf),0);//发送欢迎信息 //recv: TCP数据接收接口,返回值为实际接收到的字节数,可能小于设定值,所以需要多次recv才能读到完整数据 memset(buf,0,sizeof(buf)); while((len = recv(client_addr_sockfd,buf,128,0)) > 0) { buf[len]='\0'; printf("%s\n",buf); printf("Enter string to send:"); scanf("%s",buf); //输入“quit”退出 if(!strcmp(buf,"quit")) { break; } if(send(client_addr_sockfd,buf,len,0) < 0) { return -1; } } //关闭连接,实际只是socket的引用-1,必须引用为0才会真正关闭 close(client_addr_sockfd); close(server_sockfd); return 0; }
- client.c :
#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> #include <assert.h> #include <stdio.h> #include <string.h> #include <errno.h> int main(int argc,char* argv[]) { if(argc <= 3) { printf("usage:%s ip port backlog\n",basename(argv[0])); return 1; } const char* ip = argv[1]; int port = atoi(argv[2]); int backlog = atoi(argv[3]); struct sockaddr_in remote_addr; bzero(&remote_addr,sizeof(remote_addr)); remote_addr.sin_family = AF_INET; inet_pton(AF_INET,ip,&remote_addr.sin_addr); remote_addr.sin_port = htons(port); int remote_sockfd = socket(PF_INET,SOCK_STREAM,0); //连接 if(connect(remote_sockfd,(struct sockaddr*)&remote_addr,sizeof(struct sockaddr)) < 0) { printf("connect failed\n"); return -1; } printf("connect success\n"); int len = 0; char buf[128]; len = recv(remote_sockfd,buf,21,0); buf[len] = '\0'; printf("%s",buf); while(1) { printf("Enter string to send:"); scanf("%s",buf); if(!strcmp(buf,"quit")) { break; } send(remote_sockfd,buf,strlen(buf),0); len = recv(remote_sockfd,buf,128,0); buf[len] = '\0'; printf("received:%s\n",buf); } }