一、服务器端、客户端连接示意图
二、服务器端、客户端代码
1、服务器端代码
#include<stdio.h> #include<sys/types.h> #include<sys/socket.h> #include<unistd.h> #include<stdlib.h> #include<arpa/inet.h> #include<string.h> #include<ctype.h> int main(int argc,const char* argv[]) { if(argc<2) { printf("please input port number\n"); return -1; } int port=atoi(argv[1]);//端口号建议设置在8000以上,但是要小于65535 //1、socket创建监听 int lfd=socket(AF_INET,SOCK_STREAM,0); if(lfd==-1) { perror("socket error"); return -1; } //2、bind绑定 struct sockaddr_in serv;//定义struct sockaddr_in,而不直接定义struct sockaddr,为了方便赋值 serv.sin_family=AF_INET;//AF_INET表示ipv4 serv.sin_port=htons(port);//端口号 serv.sin_addr.s_addr=htonl(INADDR_ANY);//INADDR_ANY表示任意可连接IP,htonl是大小端转换函数,将IP转换为大端 int ret=bind(lfd,(struct sockaddr*)&serv,sizeof(serv)); if(ret==-1) { perror("bind error"); return -1; } //3、listen监听 listen(lfd,128);//参数二,同时请求连接的最大个数,范围0~128 //4、accept连接 struct sockaddr_in cli_addr; socklen_t addr_len=sizeof(cli_addr); int cfd=accept(lfd,(struct sockaddr*)&cli_addr,&addr_len); char sIP[16]={0}; const char* ip=inet_ntop(AF_INET,&cli_addr.sin_addr.s_addr,sIP,sizeof(sIP)); //5、循环读写数据 char buf[1024]; while(1) { //读数据 memset(buf,0,sizeof(buf)); int n=read(cfd,&buf,sizeof(buf)); if(n<0)//读错误 { printf("read data error\n"); break; } else if(n==0)//客户端退出 { printf("client disconnect\n"); break; } printf("client IP:%s buf:%s\n",ip,buf); //写数据 for(int i=0;i<n;++i) { buf[i]=toupper(buf[i]);//toupper将小写字符转换为大写字符 } write(cfd,buf,n); } //6、关闭文件描述符 close(lfd); close(cfd); return 0; }
2、客户端代码
#include<stdio.h> #include<sys/types.h> #include<sys/socket.h> #include<unistd.h> #include<stdlib.h> #include<arpa/inet.h> #include<string.h> #include<ctype.h> int main(int argc,const char* argv[]) { if(argc<2) { printf("please input port number\n"); return 0; } int port=atoi(argv[1]); //1、创建socket套接字 int lfd=socket(AF_INET,SOCK_STREAM,0); if(lfd==-1) { perror("socket error"); return -1; } //2、connect连接 struct sockaddr_in ser_addr; ser_addr.sin_family=AF_INET; ser_addr.sin_port=htons(port); inet_pton(AF_INET,"127.0.0.2",&ser_addr.sin_addr.s_addr);//将字符串型的IP转化为大端模式的网络IP int ret=connect(lfd,(struct sockaddr*)&ser_addr,sizeof(ser_addr)); if(ret==-1) { perror("connect errnr"); return -1; } //3、循环发送,接收数据 char buf[1024]; while(1) { //发送数据 memset(buf,0,sizeof(buf)); fgets(buf,sizeof(buf),stdin); int n=write(lfd,buf,sizeof(buf)); if(n<=0) { printf("write data error\n"); } //接收数据 memset(buf,0,sizeof(buf)); n=read(lfd,buf,sizeof(buf)); if(n<0) { printf("read data error\n"); break; }else if(n==0) { printf("server disconnect\n"); break; } printf("buf:%s\n",buf); } //4、关闭文件描述符 close(lfd); return 0; }
三、运行截图
1、服务器运行截图
2、客户端运行截图
提示:可以打开两个终端分别运行上述代码
注释:本菜鸟只提供了简单的步骤过程、代码和运行截图,至于每个步骤中使用的API函数,请移步https://www.cnblogs.com/still-smile/p/12574683.html,很详细,对socket编程和主要的API函数都做了详细的介绍。
一入编程深似海,多学多查多动手