实验环境是Ubuntu 16.01.1 LTS 32位,Linux 版本是4.4.0-1117-generic;网络环境服务器是公网IPv4,客户端是ESP8266连接的家用路由器,路由器接的二层交换机。
实验代码如下:
#include"mylib.h"
#define MAX_LISTEN 10
char buf[100]={0};
int ad[10];
struct sockaddr_in server_ip,remote_ip;
void *thread_fun(void *arg)
{
while(1)
{
read(ad[(int)arg],buf,100);
printf("buf is %s\n",buf);
printf("read data from client:%s\n",inet_ntoa(remote_ip.sin_addr));
printf("client port is %d\n",remote_ip.sin_port);
memset(buf,0,100);
}
return NULL;
}
int main()
{
int server_len,remote_len;
int i =0;
int err,sd;
pthread_t tid[10];
//创建socket
sd = socket(AF_INET,SOCK_STREAM,0);
if(sd == -1)
{
printf("create socket failed, errno is %d\n",errno);
return -1;
}
//设置ip地址和端口
server_ip.sin_family = AF_INET;
server_ip.sin_port = htons(5678);
server_ip.sin_addr.s_addr = htonl(INADDR_ANY);
memset(server_ip.sin_zero,0,8);
//绑定ip地址和端口到socket
err = bind(sd,(struct sockaddr *)(&server_ip),sizeof(struct sockaddr));
if(err == -1)
{
printf("bind error,error is %d\n",error);
close(sd);
return -2;
}
//设置服务器的最大连接数
err = listen(sd,MAX_LISTEN);
if(err == -1)
{
printf("listen error ,error is %d\n",error);
close(sd);
return -3;
}
//获取客户端ip地址的长度
remote_len = sizeof(struct sockaddr);
//利用while循环确保不停的客户端可以连接到服务器
while(1)
{
//等待客户端到请求,如果请求到来,返回一个新到socket
//服务器和客户端利用新的socket来通信
ad[i] = accept(sd,(struct sockaddr *)(&remote_ip),&remote_len);
if(ad[i] == -1)
{
printf("accept error, error is %d\n",error);
close(sd);
return -4;
}
//抛出一个新的线程,在新线程中使用while循环,确保能不停交换数据
err = pthread_create(&tid[i],NULL,thread_fun,(void *)i);
if(err != 0)
{
printf("creat new thread failed\n");
close(ad[i]);
}
i++;
}
close(sd);
return 0;
}
电脑端IP配置如下图,ESP8266和电脑连接的实验室同一台路由器,在同一网段中。
实验室网络连接电脑连的这台路由器:
TCP客户端用的是乐鑫的ESP8266测试的,烧录的是AT指令固件,上位机是安信可公司的。
TCP客户端发送信息给服务器,服务器打印客户端的IP地址、端口号和发送的数据内容: