您的位置:首页 > 理论基础 > 计算机网络

TCP套接字网络编程实例(二)

2017-07-21 15:48 363 查看

TCP套接字网络编程实例(二)

采用多线程实现客户端和服务器的聊天功能。OK,上代码。

1.客户端部分:

/*
* 文件:tcp_client.c
* 内容:利用TCP实现客户端和服务器的实时聊天。
* 注  :服务器的端口号及IP,客户端的端口号及IP的输入通过main函数的argc和argv来实现。
* 未输入端口号的话使用默认端口号,服务器为1111,客户端为2222。
* 编译:gcc tcp_chat_client.c -o cli -lpthread
* 运行:./cli 127.0.0.1 7788(注:这个是服务器端的地址和端口号)
*/

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define IP "127.0.0.1"
#define SPORT 1111
#define CPORT 2222
#define MAXLEN 1024

void* myrecv(void* arg)
{
int sock_fd = 0,len = 0;
char buf[MAXLEN] = {'\0'};
time_t t;

sock_fd = *((int*)arg);

while(1)
{
memset(buf,'\0',sizeof(buf)-1);
len = recv(sock_fd,buf,sizeof(buf) - 1,0);
if(len > 0)
{
t = time(NULL);
printf("**********************************\n");
printf("&server:%s\n",buf);
printf("**********************************\n");
printf("@%s\n",ctime(&t));
}
else if(len < 0)
{
printf("recv msg errno,errno code = %d,errno msg = %s\n",errno,strerror(errno));
break;
}
else
{
printf("connect server error,it will be quit in 3 seconds later...\n");
sleep(3);
exit(EXIT_FAILURE);
}
}
}

void* mysend(void* arg)
{
int sock_fd = 0,len = 0;
char buf[MAXLEN] = {'\0'};

sock_fd = *((int*)arg);

while(1)
{
memset(buf,'\0',sizeof(buf));

gets(buf);
if(!strncasecmp(buf,"quit",4))
{
printf("I will close the connect ...\n");
sleep(1);
exit(EXIT_FAILURE);
}
len = send(sock_fd,buf,strlen(buf),0);
if(len < 0)
{
printf("msg is:%s,send failer,errno is %d,errno message is:%s\n",buf,errno,strerror(errno));
break;
}
}
}

int main(int argc,char* argv[])
{
int pid = 0,sock_fd = 0;
socklen_t len;
struct sockaddr_in their_addr;
unsigned int their_port;
char buf[MAXLEN] = {0};
pthread_t pthread1,pthread2;

//创建socket
if((sock_fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("socket error");
exit(EXIT_FAILURE);
}

//发送连接服务器的请求
memset(&their_addr,0,sizeof(their_addr));
their_addr.sin_family = AF_INET;
if(argv[2] && argc >= 3)
their_port = atoi(argv[2]);
else
their_port = SPORT;
their_addr.sin_port = htons(their_port);

if(argv[1] && argc >=2)
{
if(inet_aton(argv[1],(struct in_addr *)&their_addr.sin_addr.s_addr) == 0)
{
perror("argv[1]");
exit(EXIT_FAILURE);
}
}
else
their_addr.sin_addr.s_addr = inet_addr(IP);

if(connect(sock_fd,(struct sockaddr*)(&their_addr),sizeof(their_addr)) == -1)
{
perror("connect error");
exit(EXIT_FAILURE);
}
printf("==============================================\n");
printf("connect success!\n");
printf("if you want to leave,please print 'quit'.\n");
printf("==============================================\n");

pthread_create(&pthread1,NULL,myrecv,(void*)&sock_fd);
pthread_create(&pthread2,NULL,mysend,(void*)&sock_fd);

pthread_join(pthread1,NULL);
pthread_join(pthread2,NULL);
close(sock_fd); //关闭套接字

return 1;
}


2.服务器部分:

/*
* 文件:tcp_server.c
* 内容:利用TCP实现客户端和服务器的实时聊天。
* 注  :服务器的端口号及IP,客户端的端口号及IP的输入通过main函数的argc和argv来实现。
* 未输入端口号的话使用默认端口号,服务器为1111,客户端为2222。
* 编译:gcc tcp_server.c -o ser -lpthread
* 运行:./ser 127.0.0.1 7788 5
*/

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define SPORT 1111
#define CPORT 2222
#define IP "127.0.0.1"
#define MAXLEN 1024

struct network_info
{
struct sockaddr addr;
int addr_len;
int sock;
}target = {0,0,0};

void* myrecv(void* arg)
{
int new_fd = 0,len = 0;
char buf[MAXLEN] = {'\0'};
time_t t;
struct network_info netinfo;
netinfo = *((struct network_info*)arg);
new_fd = netinfo.sock;

while(1)
{
memset(buf,'\0',sizeof(buf)-1);
len = recv(new_fd,buf,sizeof(buf) - 1,0);
if(len > 0)
{
t = time(NULL);
printf("&client:%s    @%s\n",buf,ctime(&t));
}
else if(len < 0)
{
printf("recv msg error,error code = %d,error msg = %s\n",errno,strerror(errno));
break;
}
else
{
printf("client is quit\n");
close(new_fd);
break;
}
}
}

void* mysend(void* arg)
{
int new_fd = 0,len = 0;
char buf[MAXLEN] = {'\0'};
struct network_info netinfo;
netinfo = *((struct network_info*)arg);

new_fd = netinfo.sock;

while(1)
{
memset(buf,'\0',sizeof(buf));

gets(buf);
if(!strncasecmp(buf,"quit",4))
{
printf("I will close the connect\n");
close(new_fd);
exit(EXIT_FAILURE);
}

len = sendto(new_fd,buf,strlen(buf),0,(struct sockaddr*)(&(netinfo.addr)),netinfo.addr_len);
if(len < 0)
{
printf("msg is:%s,send failer,errno is %d,errno message is:%s\n",buf,errno,strerror(errno));
break;
}
}
}

int main(int argc,char* argv[])
{
int pid = 0,sock_fd = 0,new_fd = 0;
socklen_t len;
struct sockaddr_in self_addr,their_addr;
unsigned int myport,lisnum;
char buf[MAXLEN] = {'\0'};
char ip[17] = {'\0'};
time_t t;
pthread_t pthread1,pthread2;

if(argv[2] && argc >=3)
myport = atoi(argv[2]);
else
myport = SPORT;

if(argv[3] && argc >= 4)
lisnum = atoi(argv[3]);
else
lisnum = 3;

//创建套接字
sock_fd = socket(AF_INET,SOCK_STREAM,0);
if(sock_fd < 0)
{
perror("socket error");
exit(EXIT_FAILURE);
}

//绑定自己的端口号
memset(&self_addr,0,sizeof(self_addr));
self_addr.sin_family = AF_INET;
self_addr.sin_port = htons(myport);
if(argv[1])
self_addr.sin_addr.s_addr = inet_addr(argv[1]);
else
self_addr.sin_addr.s_addr = INADDR_ANY;

if(bind(sock_fd,(struct sockaddr*)&self_addr,sizeof(self_addr)) == -1)
{
perror("bind error");
exit(EXIT_FAILURE);
}

//监听
if(listen(sock_fd,lisnum) == -1)
{
perror("listen error");
exit(EXIT_FAILURE);
}

//接受客户端的连接请求
memset(&their_addr,0,sizeof(their_addr));
len = sizeof(their_addr);
printf("wait for connect\n");
while(1)
{
if((new_fd = accept(sock_fd,(struct sockaddr*)&their_addr,&len)) == -1)
{
printf("len=%d,new_fd=%d\n",len,new_fd);
perror("accept error");
exit(EXIT_FAILURE);
}
printf("=====================================================================\n");
printf("client connect ok\n");
printf("though i am a server,but if you want to shutdown,please print 'quit'.\n");
printf("=====================================================================\n");
memcpy(&(target.addr),&(their_addr),len);
target.addr_len = len;
target.sock = new_fd;

//创建线程用于进程间通信
pthread_create(&pthread1,NULL,myrecv,(void*)&target);
pthread_create(&pthread2,NULL,mysend,(void*)&target);
}

pthread_join(pthread1,NULL);
pthread_join(pthread2,NULL);
close(new_fd);
close(sock_fd); //关闭套接字

return 0;
}


结果:(交叉编译后也可用,那么加上串口编程,加上select,将结构体改为字符串,字符串数据加IP地址等等然后以专有协议形成“报文”,然后和设备以相同协议通讯。)



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息