carlpc

【Galileo】socket编程实现

0
阅读(2645)

接上一篇博文

在制作的过程中,涉及了客户机与服务器的通信,采用了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) );//防止出现端口被占用,这句话非常有用
   就能解决端口被占用的问题。