Linux 网络IPC 之套接字

本文通过一个具体的示例介绍了如何使用TCP Socket进行通信。包括服务器端和客户端的代码实现,利用多线程来同时处理接收和发送数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Socket 通信,你我都懂的,今天写个小例子,采用的TCP通信方式。

server.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <signal.h>

#define SERVER_PORT 7758
#define BUFFER_SIZE 128

void my_err(char *);
void *thread_fn_recv(void *);

int main(void)
{
	printf("---------------server start------------------\n");
	int server_socket;
	struct sockaddr_in server_addr;
	server_socket=socket(AF_INET,SOCK_STREAM,0);//创建套接字	
	if(server_socket==-1)
		my_err("socket error");
	memset(&server_addr,0,sizeof(server_addr));//清空地址内存
//	bzero(&server_addr,sizeof(server_addr));//效果和上句一样
	server_addr.sin_family=AF_INET;
	server_addr.sin_port=htons(SERVER_PORT);//大小端模式转换
	void *addr=malloc(256);
	if(inet_pton(AF_INET,"192.168.122.1",addr)!=1) //将字符串形式的IP地址转换成二进制形式
		my_err("inet_pton error");
	server_addr.sin_addr.s_addr=((struct in_addr *)addr)->s_addr;
	if(bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr))==-1) //绑定本地套接字
		my_err("bind error");
	if(listen(server_socket,20)!=0) //将套接字转为被动监听状态
		my_err("listen error");
	struct sockaddr_in client_addr;
	socklen_t addr_len=sizeof(client_addr);
	int client_socket=accept(server_socket,(struct sockaddr*)&client_addr,&addr_len);//等待接收客户端的链接请求
	char ipdec[20];
	struct in_addr sin_addr;
	sin_addr.s_addr=ntohl(client_addr.sin_addr.s_addr);
	inet_ntop(AF_INET,&(client_addr.sin_addr),ipdec,16);
	printf("client IP:%s\n",ipdec); //输出客户端IP地址
	if(client_socket==-1)
		my_err("accept error");
	char buf[BUFFER_SIZE];
	pthread_t tid;
	if(pthread_create(&tid,NULL,thread_fn_recv,&client_socket)!=0) //添加新线程,专门接收客户端信息
	{
		my_err("pthread_create error");
	}
	while(1)
	{
	//	printf("server:");
		fgets(buf,BUFFER_SIZE,stdin);
		if(buf[0]=='Q'||buf[0]=='q')
		{
			pthread_kill(tid,SIGINT);
			break;
		}
		if(send(client_socket,buf,strlen(buf)+1,0)<0) //发送信息
			my_err("send error");
	}
	free(addr);
	close(client_socket);
	close(server_socket);
	printf("----------------end----------------\n");
	exit(0);
}

void *thread_fn_recv(void *arg) 
{
	int len;
	char buf2[BUFFER_SIZE];
	int client_socket=*(int*)arg;
	while(1)
	{
		len=recv(client_socket,buf2,BUFFER_SIZE,0);
		if(len<0)
			my_err("recv error");
		else if(len==0)
		{
			printf("client has shutdown\n");
			pthread_exit(0);
		}
		printf("client:%s",buf2);
		fflush(stdout);
	}
	printf("recv end\n");
	return 0;
}

void my_err(char *str)
{
	perror(str);
	exit(1);
}

client.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <signal.h>

#define SERVER_PORT 7758
#define BUFFER_SIZE 128

void my_err(char *);
void *thread_fn_recv(void *);

int main(void)
{
	printf("------------client start--------------\n");
	int client_socket;
	struct sockaddr_in client_addr;
	bzero(&client_addr,sizeof(client_addr));
	client_addr.sin_family=AF_INET;
	client_addr.sin_port=htons(0);	
	client_addr.sin_addr.s_addr=htonl(INADDR_ANY);
	client_socket=socket(AF_INET,SOCK_STREAM,0);//创建套接字
	if(client_socket<0)
		my_err("socket error");
	if(bind(client_socket,(struct sockaddr*)&client_addr,sizeof(client_addr))<0) //绑定
		my_err("bind error");
	struct sockaddr_in server_addr;
	server_addr.sin_family=AF_INET;
	server_addr.sin_port=htons(SERVER_PORT);//大小端模式转换。TCP/IP协议栈采用大端字节序。
	void *addr=malloc(128);
	if(inet_pton(AF_INET,"192.168.122.1",addr)!=1) //Convert IPv4 or IPV6 addresses from text to binary form.
		my_err("inet_pton error");
	server_addr.sin_addr.s_addr=((struct in_addr*)addr)->s_addr;
	if(connect(client_socket,(struct sockaddr*)&server_addr,sizeof(server_addr))<0) //连接服务器
		my_err("connect error");
	char buf2[BUFFER_SIZE];
	pthread_t tid;
	if(pthread_create(&tid,NULL,thread_fn_recv,&client_socket)!=0) //开启一个新线程,专门接收信息
	{
		my_err("pthread_create error");
	}
	while(1)
	{
//		printf("client:");
		fgets(buf2,BUFFER_SIZE,stdin);
		if(buf2[0]=='Q'||buf2[0]=='q')
		{
			pthread_kill(tid,SIGINT);
			break;
		}
		if(send(client_socket,buf2,strlen(buf2)+1,0)<0) //发送信息
			my_err("send error");
	}
	free(addr);
	close(client_socket);
	printf("-----------------end--------------------\n");
	exit(0);
}

void *thread_fn_recv(void *arg)
{
	int client_socket=*(int *)arg;
	int len;
	char buf[BUFFER_SIZE];
	while(1)
	{
		len=recv(client_socket,buf,BUFFER_SIZE,0);
		if(len<0)
			my_err("recv error");
		else if(len ==0)
		{
			printf("server shutdown\n");
			pthread_exit(0);
		}
		printf("server:%s",buf);
	}
	return 0;
}

void my_err(char *str)
{
	perror(str);
	exit(1);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值