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