linux学习笔记18-网络通信socket和多线程
客户端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
//接收socket的线程执行函数
void *recv_socket(void *arg)
{
if(arg == NULL)
{
printf("arg is NULL!\n");
return NULL;
}
int sock = *(int *)arg;
char buf[1024];
while(1)
{
memset(buf,0,sizeof(buf));
int msg_len = recv(sock,buf,sizeof(buf),0); //接收消息
if(msg_len > 0)
{
printf("server msg:%s",buf);
}
else
{
break;
}
}
return NULL;
}
//发送socket的线程执行函数
void *send_socket(void *arg)
{
if(arg == NULL)
{
printf("arg is NULL!\n");
return NULL;
}
int sock = *(int *)arg;
char buf[1024];
while(1)
{
memset(buf,0,sizeof(buf));
read(STDIN_FILENO,buf,sizeof(buf));
send(sock,buf,strlen(buf),0); //将消息发送
}
}
int main(int argc,char *argv[])
{
if(argc < 3)
{
printf("argc < 3\n");
return -1;
}
int port = atoi(argv[2]);
int sock = socket(AF_INET,SOCK_STREAM,0); //初始化socket
struct sockaddr_in addr; //ip地址结构
memset(&addr,0,sizeof(addr)); //初始化ip结构
addr.sin_family = AF_INET; //设置结构类型类tcp/ip地址
addr.sin_port = htons(port); //指定一个端口号, htons将short类型从host字节类型换net字节类型
addr.sin_addr.s_addr = inet_addr(argv[1]); //将ip地址转为int类型数据,赋值给s_addr
if(connect(sock,(struct sockaddr *)&addr,sizeof(addr)) == -1)
{
printf("connect failed:%s\n",strerror(errno));
return -1;
}
pthread_t thread1,thread2;
pthread_create(&thread1,NULL,recv_socket,&sock); //开启线程,执行recv_socket函数
pthread_create(&thread2,NULL,send_socket,&sock); //开启线程,执行send_socket函数
pthread_join(thread1,NULL);
close(sock);
return 0;
}
服务端(重点在服务端)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
//线程调用只能有一个参数,有多个线程参数的时候,需要用结构体进行封装
struct pthread_socket
{
int sock; //socket文件描述符
pthread_t *thread; //线程id
};
//接收socket的线程
void *recv_socket(void *argc)
{
if(argc == NULL)
{
printf("recv_socket arg is NULL!\n");
return NULL;
}
struct pthread_socket * ps = (struct pthread_socket *)argc; //将argc强制转为pthread_socket结构类型的指针
int sock = ps->sock;
char buf[1024];
while(1)
{
memset(buf,0,sizeof(buf));
int rec = recv(sock,buf,sizeof(buf),0); //接收消息
if(rec > 0)
{
printf("client msg:%s",buf);
}
else
{
//关闭和出错
break;
}
}
pthread_cancel(*(ps->thread)); //线程退出的时候,让线程2也退出
return NULL;
}
//发送socket的线程
void *send_socket(void *argc)
{
if(argc == NULL)
{
printf("send_socket argc is NULL!\n");
return NULL;
}
int sock = *(int *)argc;
char buf[1024];
while(1)
{
memset(buf,0,sizeof(buf));
read(STDIN_FILENO,buf,sizeof(buf));
send(sock,buf,strlen(buf),0);
}
return NULL;
}
int main(int argc,char *argv[])
{
if(argc <2 )
{
printf("argc < 2!\n");
return -1;
}
int port = atoi(argv[1]);
int sock = socket(AF_INET,SOCK_STREAM,0); //初始化socket
int on = 1;
if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) == -1)
{
printf("setscoket failed:%s\n",strerror(errno));
return -1;
}
struct sockaddr_in addr; //ip地址结构
memset(&addr,0,sizeof(addr)); //初始化ip结构
addr.sin_family = AF_INET; //设置结构类型类tcp/ip地址
addr.sin_port = htons(port); //指定一个端口号, htons将short类型从host字节类型换net字节类型 ,将本地字节顺序转换为网络字节顺序
addr.sin_addr.s_addr = htonl(INADDR_ANY); //服务器的所有地址
if(bind(sock,(struct sockaddr *)&addr,sizeof(addr)) == -1) //将ip与server程序绑定
{
printf("bind failed:%s\n",strerror(errno));
return -1;
}
if(listen(sock,20) == -1) //开始监听
{
printf("listen failed:%s\n",strerror(errno));
return -1;
}
char buf[1024];
int client_sock = 0;
struct sockaddr_in client_addr; //表示client的ip地址
void *p = &client_addr;
pthread_t pthread1,pthread2;
while(1)
{
memset(&client_addr,0,sizeof(client_addr));
int len = sizeof(client_addr);
client_sock = accept(sock,p,&len); //accept会阻塞,直到客户端连接过来,返回client的socket描述符
if(client_sock == -1)
{
printf("accept failed:%s\n",strerror(errno));
return -2;
}
printf("accept ip:%s\n",inet_ntoa(client_addr.sin_addr));
struct pthread_socket ps;
ps.sock = client_sock;
ps.thread = &pthread2; //传递线程2 id的地址
pthread_create(&pthread1,NULL,recv_socket,(void *)&ps);
pthread_detach(pthread1); //分离线程(线程结束后,系统会将线程资源进行回收)
pthread_create(&pthread2,NULL,send_socket,(void *)&client_sock);
pthread_detach(pthread2);
//pthread_join(pthread1,NULL);
//pthread_join(pthread2,NULL);
}
close(client_sock);
close(sock);
return 0;
}
秋风
2016-12-03