linux網絡編程的幾個簡單例子

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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章