1.socket是一个常用的网络通信API,今天就学习一下多线程配合socket进行通信。
服务端server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define SERVERPORT 9009
#define BACKLOG 10
#define HI "success!\n"
#define END "end"
static int server_fd = -1, client_fd = -1;
static void *create_server(void)
{
int ret = -1;
struct sockaddr_in server_addr = {0}, client_addr = {0};
socklen_t sock_len = 0;
char recv_buf[128] = {0};
server_fd = socket(AF_INET, SOCK_STREAM, 0); //创建socket句柄
if(server_fd < 0)
{
perror("socket");
return NULL;
}
server_addr.sin_family = AF_INET; //设置ipv4协议
server_addr.sin_port = htons(SERVERPORT); //设置端口
server_addr.sin_addr.s_addr = INADDR_ANY; //设置ip地址为本机地址
ret = bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)); //绑定地址
if(ret == -1)
{
perror("server bind");
return NULL;
}
ret = listen(server_fd, BACKLOG); //监听地址
if (ret < 0)
{
perror("listen");
return NULL;
}
client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &sock_len); //等待服务端连接
printf("client connected, fd = %d\n", client_fd);
while(1)
{
ret = send(client_fd, HI, sizeof(HI), 0); //发送success给客户端
printf("send to client msg length = %d\n", ret);
ret = recv(client_fd, &recv_buf, sizeof(recv_buf), 0); //接收客户端传递的消息
printf("recv from client msg: %s\n", recv_buf);
if(strncmp(END, recv_buf, sizeof(END)) == 0) //接收到end,结束通信
{
ret = send(client_fd, recv_buf, strlen(recv_buf), 0);
printf("server exited, send last msg to client length = %d\n",ret);
return NULL;
}
memset(recv_buf, 0, sizeof(recv_buf));
}
return NULL;
}
int main(int argc, char const *argv[])
{
int ret = -1;
pthread_t pt = -1;
ret = pthread_create(&pt, NULL, (void *)create_server, NULL); //创建子线程
if(ret != 0)
{
perror("pthread_create");
goto out;
}
ret = pthread_join(pt, NULL); //等待线程结束
if(ret != 0)
{
perror("pthread_join");
}
out:
if(server_fd != -1) close(server_fd); //释放资源
if(client_fd != -1) close(client_fd);
return 0;
}
客户端client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define SERVERPORT 9009
#define END "end"
static int client_fd = -1;
static int init(void)
{
int ret = -1;
struct sockaddr_in client_addr = {0};
client_fd = socket(AF_INET, SOCK_STREAM, 0); //创建socket句柄
if(client_fd < 0)
{
perror("socket");
return -1;
}
client_addr.sin_family = AF_INET; //和服务端一毛一样
client_addr.sin_port = htons(SERVERPORT);
client_addr.sin_addr.s_addr = INADDR_ANY;
ret = connect(client_fd, (struct sockaddr *)&client_addr, sizeof(struct sockaddr_in)); //连接到服务端
if(ret == -1)
{
perror("connect");
return -1;
}
return 0;
}
static void *recv_thread(void)
{
int ret = -1;
char recv_buf[128] = {0};
while(1)
{
ret = recv(client_fd, &recv_buf, sizeof(recv_buf), 0); //接收服务端发过来的success信息
printf("recv from server: %s\n", recv_buf);
if(strncmp(END, recv_buf, sizeof(END)) == 0) //收到end结束子线程
{
printf("client exited!\n");
return NULL;
}
memset(recv_buf, 0, sizeof(recv_buf));
}
return NULL;
}
static void *intput_thread(void)
{
char input_buf[128] = {0};
int ret = -1;
while(1)
{
scanf("%s", input_buf); //键盘输入
ret = send(client_fd, input_buf, strlen(input_buf), 0); //发送键盘输入的信息
printf("intput_thread send to server msg length = %d\n", ret);
if(strncmp(END, input_buf, sizeof(END)) == 0) //输入end结束子线程
{
printf("intput_thread exited!\n");
return NULL;
}
memset(input_buf, 0, sizeof(input_buf));
}
return NULL;
}
int main(int argc, char const *argv[])
{
int ret = -1;
pthread_t pt1 = -1, pt2 = -1;
if(init())
{
return -1;
}
ret = pthread_create(&pt1, NULL, (void *)recv_thread, NULL);
if(ret != 0)
{
perror("pthread_create");
goto out;
}
ret = pthread_create(&pt2, NULL, (void *)intput_thread, NULL);
if(ret != 0)
{
perror("pthread_create");
goto out;
}
ret = pthread_join(pt1, NULL);
if(ret != 0)
{
perror("pthread_join pt1");
}
ret = pthread_join(pt2, NULL);
if(ret != 0)
{
perror("pthread_join pt2");
}
out:
if(client_fd != -1) close(client_fd);
return 0;
}
简单Makefile进行编译
all:
gcc client.c -o client -pthread
gcc server.c -o server -pthread