【Galileo】socket编程实现
0赞接上一篇博文
在制作的过程中,涉及了客户机与服务器的通信,采用了tcp的方式进行连接,因此本文主要总结了socket编程的过程中的基本步骤,以及设计过程中的遇到的问题和解决的方式
socket编程涉及了客户端和服务端,两端的操作不一样,具体如下:
****************************************************************************************
服务器流程:
创建套接字--->定义服务器端的地址--->将套接字与定义的地址绑定--->监听--->接受连接请求--->收发--->关闭
|
________________ |
客户端流程: |
创建套接字--->设置要连接的服务器地址--->提出连接服务器请求--->收发操作--->关闭套接字
****************************************************************************************
通过这两个流程就能实现socket的通信,接下来一代码的实现来说明
服务器:
#include <iostream> #include <string.h> #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdlib.h> #include <syslog.h> #include <errno.h> using namespace std; #define MAX_LISTEN_NUM 5 #define SEND_BUF_SIZE 100 #define RECV_BUF_SIZE 100 #define LISTEN_PORT 8887 int main(int argc,char *argv[]) { struct sockaddr_in ser_addr; struct sockaddr_in cli_addr; int err,ss,sc; char buffer[1024]; //*********************** // socket //AF_UNIX(本机通信) //AF_INET(TCP/IP – IPv4) //AF_INET6(TCP/IP – IPv6) //********************** ss=socket(AF_INET,SOCK_STREAM,0);//创建套接字 int on =1; setsockopt( ss, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );//防止出现端口被占用,这句话非常有用 if(ss<0) cout<<"creat erro"<<endl; else cout<<"created"<<endl; //*********************** // bind // //*********************** memset(&ser_addr,0,sizeof(ser_addr));//initial ser_addr.sin_family=AF_INET;//设置为TCP/IP – IPv4 ser_addr.sin_port=htons(LISTEN_PORT);//绑定端口 ser_addr.sin_addr.s_addr=htonl(INADDR_ANY);//接收的地址 err=bind(ss,(struct sockaddr *)&ser_addr,sizeof(ser_addr));//套接字绑定 if(err<0) cout<<"bind erro"<<endl; else cout<<"bind"<<endl; //*********************** // listen //*********************** err=listen(ss,MAX_LISTEN_NUM);//监听 if(err<0) cout<<"listen erro"<<endl; else cout<<"listen"<<endl; socklen_t addrlen = sizeof(cli_addr); sc=accept(ss,(struct sockaddr *)&cli_addr,&addrlen);//接受连接请求 if(sc<0) cout<<"accept erro"<<endl; else cout<<"accept"<<endl; cout<<"********************"<<endl; send(sc,"********************",20,0); cout<<ss<<","<<sc<<endl; while(1) //进行收发操作 { memset(buffer,0,sizeof(buffer)); int len = recv(sc, buffer, sizeof(buffer),0);//这里是sc不是ss if(strcmp(buffer,"exit\n")==0) break; fputs(buffer, stdout); send(sc, buffer, len, 0); //这里是sc不是ss } close(sc); close(ss); return 0; }
客户端:
#include <iostream> #include <string.h> #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdlib.h> #include <syslog.h> #include <errno.h> #include <arpa/inet.h> using namespace std; #define MAX_LISTEN_NUM 5 #define SEND_BUF_SIZE 100 #define RECV_BUF_SIZE 100 #define PORT 8887 int main(int argc,char **argv) { struct sockaddr_in ser_addr; char buff[100]; int err,ss,sc; //*********************** // socket //AF_UNIX(本机通信) //AF_INET(TCP/IP – IPv4) //AF_INET6(TCP/IP – IPv6) //********************** ss=socket(AF_INET,SOCK_STREAM,0); //创建套接字 int on =1; setsockopt( ss, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ); if(ss<0) cout<<"creat erro"<<endl; else cout<<"created"<<endl; //*********************** // set //********************** memset(&ser_addr,0,sizeof(ser_addr));//initial ser_addr.sin_family=AF_INET;//设置为TCP/IP – IPv4 ser_addr.sin_port=htons(PORT);//绑定端口与服务器相同 inet_aton("192.168.159.131",(struct in_addr *)&ser_addr.sin_addr);//要连接的地址,可指定也可任意 err=connect(ss,(struct sockaddr *)&ser_addr,sizeof(sockaddr));//提出连接请求 if(err<0) cout<<"connect erro"<<endl; else cout<<"connect"<<endl; char sendbuf[1024]; char recvbuf[1024]; int num=recv(ss, recvbuf, sizeof(recvbuf),0); ///接收 recvbuf[num]='\0'; printf("%s\n",recvbuf); while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) { send(ss, sendbuf, strlen(sendbuf),0); ///发送 if(strcmp(sendbuf,"exit\n")==0) break; recv(ss, recvbuf, sizeof(recvbuf),0); ///接收 fputs(recvbuf, stdout); memset(sendbuf, 0, sizeof(sendbuf)); memset(recvbuf, 0, sizeof(recvbuf)); } close(ss); return 0; }
以上就是实现的代码,那么在设计过程中出现了两个主要的问题:
1、服务器端:一开始编程的时候,比较马虎,在连接成功后,收发的过程中,要使用客户端的套接字,即accept函数的返回值sc,而不是ss,这样才能收发成功;
2、共同的问题:端口占用的问题,因为在使用的过程中,会出现异常断开的现象,而直接退出,并未解绑端口,再重新运行的过程中,会显示端口被占用,导致重新绑定失败,因此,经过查阅资料在创建套接字后加入:
int on =1; setsockopt( ss, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );//防止出现端口被占用,这句话非常有用就能解决端口被占用的问题。