TCP连接的多进程收发

1)服务器端

1.需要先获得socket

fd = socket(AF_INET, SOCK_DGRAM, 0);

AF_INET代表使用IPV4协议族

SOCK_DGRAM代表TCP/IP连接

 

2.bind()  把获得的socket和要监听的ip端口绑定起来

3.listen()启动监测数据

4.accept()接受/建立一条连接 等待客户端连接

5.send() 发数据

recv() 收数据

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>


/* socket
 * bind
 * listen
 * accept
 * send/recv
 */

#define SERVER_PORT 7897
#define BACKLOG     10

int main(int argc, char **argv)
{
	int iSocketServer;
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr; //指定服务器绑定地址
	struct sockaddr_in tSocketClientAddr; //保存客户端地址
	int iRet;
	int iAddrLen;

	int iRecvLen;
	unsigned char ucRecvBuf[1000];

	int iClientNum = -1;

	signal(SIGCHLD,SIG_IGN); //此函数用于处理僵尸进程
	
	iSocketServer = socket(AF_INET, SOCK_STREAM, 0);//AF_INET IPV4连接 SOCK_STREAM启动TCP连接
	if (-1 == iSocketServer)
	{
		printf("socket error!\n");
		return -1;
	}

	tSocketServerAddr.sin_family      = AF_INET; //一般设置为
	tSocketServerAddr.sin_port        = htons(SERVER_PORT); //将SERVER_PORT转化为网络字节序 host to net, short
 	tSocketServerAddr.sin_addr.s_addr = INADDR_ANY; //INADDR_ANY表示本机上所有IP
	memset(tSocketServerAddr.sin_zero, 0, 8);


	int opt = 1;  
    //使用setsockopt函数可以保证端口可被重复绑定
    iRet = setsockopt(iSocketServer, SOL_SOCKET,SO_REUSEADDR,   
    				(const void *)&opt, sizeof(opt) );	
	if (-1 == iRet)
	{
		printf("set sock option error!\n");
		close(iSocketServer);
		return -1;
	}
	
	
	iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr)); //绑定端口
	if (-1 == iRet)
	{
		printf("bind error!\n");
		close(iSocketServer);
		return -1;
	}

	iRet = listen(iSocketServer, BACKLOG); //设置监听 BACKLOG代表同时监听10路连接
	if (-1 == iRet)
	{
		printf("listen error!\n");
		return -1;
	}

	while (1)
	{
		iAddrLen = sizeof(struct sockaddr);
		iSocketClient = accept(iSocketServer, (struct sockaddr *)&tSocketClientAddr, &iAddrLen); //等待连接 如果建立连接
		if (-1 != iSocketClient)
		{
			iClientNum++;
			printf("Get connect from client %d : %s\n",  iClientNum, inet_ntoa(tSocketClientAddr.sin_addr));
			if (!fork()) //fork创建子进程 返回值为0的是子进程 
			{
				/* 子进程中处理客户端数据 */
				while (1)
				{
					/* 接收客户端发来的数据并显示出来 */
					iRecvLen = recv(iSocketClient, ucRecvBuf, 999, 0);
					if (iRecvLen <= 0)
					{
						close(iSocketClient); //关闭连接
						return -1;
					}
					else
					{
						ucRecvBuf[iRecvLen] = '\0';
						printf("Get Msg From Client %d: %s\n", iClientNum, ucRecvBuf);
						send(iSocketClient, "ok", 2, 0);//打印的同时发送一条数据给连接的客户端
					}
				}				
			}
		}
	}
	
	close(iSocketServer);
	return 0;
}


服务器端每收到一个客户端连接都会使用fork()创建一个子进程。每个子进程分别处理自己的数据请求。

关于fork()函数的详解可以看看这篇文章https://blog.csdn.net/weixin_42736024/article/details/81412962

 

2)客户端

1、获取socket

iSocketClient = socket(AF_INET, SOCK_STREAM, 0);

AF_INET代表使用IPV4协议族

SOCK_STREAM代表tcp/ip连接

2、将获取的ip 使用inet_aton()转化为能用的ip

3、将socket链接到指定端口

connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));

3、send(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0); 发送数据

 

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>

/* socket
 * connect
 * send/recv
 */

#define SERVER_PORT 8888

int main(int argc, char **argv)
{
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr;
	
	int iRet;
	unsigned char ucSendBuf[1000];
	int iSendLen;

	if (argc != 2)
	{
		printf("Usage:\n");
		printf("%s <server_ip>\n", argv[0]);
		return -1;
	}

	iSocketClient = socket(AF_INET, SOCK_STREAM, 0); //获得socket

    //设置需要连接的ip端口
	tSocketServerAddr.sin_family      = AF_INET;
	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /*将端口转化成网络字节序 */
 	//tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
 	if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr)) //将命令行读入的字符串ip转化成能用的ip
 	{
		printf("invalid server_ip\n");
		return -1;
	}
	memset(tSocketServerAddr.sin_zero, 0, 8);


	iRet = connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));//建立连接
	if (-1 == iRet)
	{
		printf("connect error!\n");
		return -1;
	}

	while (1)
	{
		if (fgets(ucSendBuf, 999, stdin))//从标准输入获得数据 以回车为结尾
		{
			iSendLen = send(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0);
			if (iSendLen <= 0)
			{
				close(iSocketClient);
				return -1;
			}
		}
	}
	
	return 0;
}

 

 

UDP连接

1)服务器

fd=socket()

bind()绑定IP端口

revfrom()接收数据

sendto()发送数据

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>


/* socket
 * bind
 * sendto/recvfrom
 */

#define SERVER_PORT 8888

int main(int argc, char **argv)
{
	int iSocketServer;
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr;
	struct sockaddr_in tSocketClientAddr;
	int iRet;
	int iAddrLen;

	int iRecvLen;
	unsigned char ucRecvBuf[1000];

	int iClientNum = -1;
	
	iSocketServer = socket(AF_INET, SOCK_DGRAM, 0); //SOCK_DGRAM代表UDP连接
	if (-1 == iSocketServer)
	{
		printf("socket error!\n");
		return -1;
	}

	tSocketServerAddr.sin_family      = AF_INET;
	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
 	tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
	memset(tSocketServerAddr.sin_zero, 0, 8);
	
	iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
	if (-1 == iRet)
	{
		printf("bind error!\n");
		return -1;
	}


	while (1)
	{
		iAddrLen = sizeof(struct sockaddr);
		iRecvLen = recvfrom(iSocketServer, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
		if (iRecvLen > 0)
		{
			ucRecvBuf[iRecvLen] = '\0';
			printf("Get Msg From %s : %s\n", inet_ntoa(tSocketClientAddr.sin_addr), ucRecvBuf);
		}
	}
	
	close(iSocketServer);
	return 0;
}


2)客户端

fd=socket

connect()    UDP连接的connect实际上不会进行连接只会绑定IP端口

sendto()或者send()发送数据

recvform() 或者recv()接收数据

 

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>

/* socket
 * connect
 * send/recv
 */

#define SERVER_PORT 8888

int main(int argc, char **argv)
{
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr;
	
	int iRet;
	unsigned char ucSendBuf[1000];
	int iSendLen;

	if (argc != 2)
	{
		printf("Usage:\n");
		printf("%s <server_ip>\n", argv[0]);
		return -1;
	}

	iSocketClient = socket(AF_INET, SOCK_DGRAM, 0);

	tSocketServerAddr.sin_family      = AF_INET;
	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
 	//tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
 	if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))
 	{
		printf("invalid server_ip\n");
		return -1;
	}
	memset(tSocketServerAddr.sin_zero, 0, 8);


	iRet = connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));	
	if (-1 == iRet)
	{
		printf("connect error!\n");
		return -1;
	}

	while (1)
	{
		if (fgets(ucSendBuf, 999, stdin))
		{
			iSendLen = send(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0);
			if (iSendLen <= 0)
			{
				close(iSocketClient);
				return -1;
			}
		}
	}
	
	return 0;
}

 

 

UDP服务器多线程收发

1)服务器

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>


/* socket
 * bind
 * sendto/recvfrom
 */

#define SERVER_PORT 5678

static pthread_t g_tSendTreadID;
static pthread_t g_tRecvTreadID;


static pthread_mutex_t g_tSendMutex  = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t  g_tSendConVar = PTHREAD_COND_INITIALIZER;

static struct sockaddr_in tSocketServerAddr;
static struct sockaddr_in tSocketClientAddr;

int iSocketServer;
int iSocketClient;


static void *SendTreadFunction(void *pVoid)
{
   int iAddrLen = sizeof(struct sockaddr);
  while(1)
  {

    /* 平时休眠 */
	pthread_mutex_lock(&g_tSendMutex);
	pthread_cond_wait(&g_tSendConVar, &g_tSendMutex);	
	pthread_mutex_unlock(&g_tSendMutex);

    sendto(iSocketServer, "ok\n", 2, 0,(const struct sockaddr *)&tSocketClientAddr, iAddrLen);
   
  }
}

int main(int argc, char **argv)
{

	int iRet;
	int iAddrLen;

	int iRecvLen;
	unsigned char ucRecvBuf[1000];

	int iClientNum = -1;

	iSocketServer = socket(AF_INET, SOCK_DGRAM, 0); //获得socket
	if (-1 == iSocketServer)
	{
		printf("socket error!\n");
		return -1;
	}

	tSocketServerAddr.sin_family      = AF_INET;
	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
 	tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
	memset(tSocketServerAddr.sin_zero, 0, 8);

	int opt = 1;  
    iRet = setsockopt(iSocketServer, SOL_SOCKET,SO_REUSEADDR,   
    				(const void *)&opt, sizeof(opt) );	//使用此函数可以保证端口可被重复绑定
	if (-1 == iRet)
	{
		printf("set sock option error!\n");
		close(iSocketServer);
		return -1;
	}
	
	iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr)); //将socket与ip端口绑定在一起
	if (-1 == iRet)
	{
		printf("bind error!\n");
		close(iSocketServer);
		return -1;
	}

    /* 创建netprint发送线程: 它用来发送打印信息给客户端 */
	pthread_create(&g_tSendTreadID, NULL, SendTreadFunction, NULL);	
	//pthread_create(&g_tRecvTreadID, NULL, RecvTreadFunction, NULL);

	while (1)
	{
		iAddrLen = sizeof(struct sockaddr);
		iRecvLen = recvfrom(iSocketServer, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
		if (iRecvLen > 0)
		{
			ucRecvBuf[iRecvLen] = '\0';
			printf("Get Msg From %s : %s\n", inet_ntoa(tSocketClientAddr.sin_addr), ucRecvBuf);

            //唤醒发送线程
			pthread_mutex_lock(&g_tSendMutex);
			pthread_cond_signal(&g_tSendConVar);
			pthread_mutex_unlock(&g_tSendMutex);	
		}
	}
	
	close(iSocketServer);
	return 0;
}


2)客户端

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>

/* socket
 * connect
 * send/recv
 */

#define SERVER_PORT 5678

int main(int argc, char **argv)
{
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr;
	struct sockaddr_in tSocketClientAddr;
	int iRet;
	int iRecvLen;
	unsigned char ucSendBuf[1000];
	unsigned char ucRecvBuf[1000];
	int iSendLen;
	int iAddrLen;

	if (argc != 2)
	{
		printf("Usage:\n");
		printf("%s <server_ip>\n", argv[0]); //
		return -1;
	}

	iSocketClient = socket(AF_INET, SOCK_DGRAM, 0); //申请socket

	tSocketServerAddr.sin_family      = AF_INET;
	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
 	//tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
 	if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))//将输入的ip地址转化成网络字节序
 	{
		printf("invalid server_ip\n");
		return -1;
	}
	memset(tSocketServerAddr.sin_zero, 0, 8);



	while (1)
	{
		if (fgets(ucSendBuf, 999, stdin))
		{

			iAddrLen = sizeof(struct sockaddr);
			iSendLen = sendto(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0,
			                      (const struct sockaddr *)&tSocketServerAddr, iAddrLen);
			
			if (iSendLen <= 0)
			{
				close(iSocketClient);
				return -1;
			}
		}


		iAddrLen = sizeof(struct sockaddr);
		//收到来自 inet_ntoa(tSocketClientAddr.sin_addr)     地址的信息
		iRecvLen = recvfrom(iSocketClient, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen); 

		if (iRecvLen > 0)	
		{

           printf("Get Msg From %s : %s\n", inet_ntoa(tSocketClientAddr.sin_addr), ucRecvBuf);
		}

		
	}
	
	return 0;
}

 

Logo

更多推荐