【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) );//防止出现端口被占用,这句话非常有用就能解决端口被占用的问题。
