日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

在寫面向UDP連接的 socket 的通信程序時,我先總結歸納一些關于面向TCP和UDP連接的socket 通信程序的相關知識:

面向TCP連接的 socket 通信程序:

服務端:創(chuàng)建套接字,指定協(xié)議族(sockaddr_in),綁定,監(jiān)聽,接受連接,發(fā)送或接受數(shù)據(jù),關閉連接;

客戶端:創(chuàng)建套接字,指定協(xié)議族,連接(connect),發(fā)送或接受數(shù)據(jù),關閉連接;

TCP在接受數(shù)據(jù)時:write/send/sendto, read/recv/recvfrom都可以用, 通常會用send, recv;

但在面向UDP的socket程序中,發(fā)送數(shù)據(jù)時用sendto的話,就不用connect了,但是在面向TCP的程序中,在發(fā)送數(shù)據(jù)時,即使用sendto,也必須用connect

面向UDP連接的socket通信程序:

服務端:創(chuàng)建套接字,指定協(xié)議族(sockaddr_in),綁定(不需要listen和accept),發(fā)送或接收數(shù)據(jù);

客戶端:創(chuàng)建套接字,指定協(xié)議族,連接(和TCP的客戶端步驟一樣),發(fā)送或接受數(shù)據(jù);

UDP常用sendto,recvfrom; 注意:用sendto時,就不用connect了(用了也沒事),其他的(write, send)

必須用connect;

補充:1、無論是TCP還是UDP,默認情況下創(chuàng)建的都是阻塞模式的套接字,執(zhí)行到(accept,connect, write/send/sento,read/recv/recvfrom)等語句時,會一直等待(connect)有點列外,它連接一段時間,如果連接不成功,會以錯誤形式返回,不會一直等待

2、可以把socket設置成非阻塞模式, linux下用fcntl函數(shù),TCP和UDP設置成非阻塞模式以后,效果是一樣的,都不再等待而是立即返回

3、TCP面向連接, UDP面向無連接

TCP:客戶端退出程序時或斷開連接時,TCP的這個函數(shù)會立即返回不在阻塞(因為服務端自己知道客戶端已經退出或斷開連接,證明它是面向連接的)

UDP:始終保持阻塞(服務端不知道客戶端已經退出或斷開連接,證明它是面向無連接的)

4、TCP無邊界,UDP有邊界

TCP:客戶端連續(xù)發(fā)送數(shù)據(jù),只要服務端的這個函數(shù)的緩沖區(qū)足夠大,會一次性接收過來

(客戶端是分好幾次發(fā)過來,是有邊界的,而服務端卻一次性接收過來,所以證明是無邊界的)

UDP:客戶端連續(xù)發(fā)送數(shù)據(jù),即使服務端的這個函數(shù)的緩沖區(qū)足夠大,也只會一次一次的接收,客戶端分幾次發(fā)送過來,服務端就必須按幾次接收

補充:

1、socket()的參數(shù)不同

2、UDP Server不需要調用listen和accept

3、UDP收發(fā)數(shù)據(jù)用sendto/recvfrom函數(shù)

4、UDP:shutdown函數(shù)無效

5、TCP:地址信息在connect/accept時確定 UDP:在sendto/recvfrom函數(shù)中每次均需指定地址信息Sendto()和recvfrom()用于在無連接的數(shù)據(jù)報socket方式下進行數(shù)據(jù)傳輸。由于本地socket并沒有與遠端機器進行連接,所以在發(fā)送數(shù)據(jù)時應指明目的地址

下面就是我寫的利用UDP連接和多線程實現(xiàn)的客戶端之間的通信代碼:

服務器端:UdpServer.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
 
#define PORT 8888
 
struct info
{
	char buf[100];
	int port;
};
 
int main()
{
	int sockfd, length, ret, j, i = 0;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr[10] = {0};
	struct sockaddr_in tmp_addr;
	struct info RecvBuf = {0};
 
	sockfd = socket(PF_INET, SOCK_DGRAM, 0);
	if (-1 == sockfd)
	{
		perror("socket");
		exit(1);
	}
 
	bzero(&server_addr, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = PORT;
	server_addr.sin_addr.s_addr = inet_addr("192.168.0.128");
 
	ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
	if (ret < 0)
	{
		perror("bind");
		exit(1);
	}
	while (1)
	{
		length = sizeof(client_addr[0]);
		ret = recvfrom(sockfd, &RecvBuf, sizeof(RecvBuf), 0, (struct sockaddr *)&tmp_addr, &length);
		if (ret < 0)
		{
			perror("recvfrom");
			exit(1);
		}
		printf("Recv From Client %d : %sn", tmp_addr.sin_port, RecvBuf.buf);
		if (0 == i)
		{
			client_addr[0].sin_family = tmp_addr.sin_family;
			client_addr[0].sin_port = tmp_addr.sin_port;
			client_addr[0].sin_addr.s_addr = tmp_addr.sin_addr.s_addr;
			i++;
		}
		else
		{
			for (j = 0; j < i; j++)
			{
				if (tmp_addr.sin_port == client_addr[j].sin_port)
				{
					break;
				}
				if (j == i - 1)
				{
					client_addr[i].sin_family = tmp_addr.sin_family;
			    	        client_addr[i].sin_port = tmp_addr.sin_port;
					client_addr[i].sin_addr.s_addr = tmp_addr.sin_addr.s_addr;
					i++;
				}
			}
		}
		if (!strcmp(RecvBuf.buf, "bye"))
		{
			break;
		}
		strcat(RecvBuf.buf, "-server");
		for(j = 0; j < i; j++)
		{
			if (RecvBuf.port == client_addr[j].sin_port)
			{
				break;
			}
			if (j == i - 1)
			{
				break;
			}
		}
	
		ret = sendto(sockfd, &RecvBuf, sizeof(RecvBuf), 0, (struct sockaddr *)&client_addr[j], sizeof(client_addr[0]));
		if (ret < 0)
		{
			perror("sendto");
			exit(1);
		}
		memset(&RecvBuf, 0, sizeof(RecvBuf));
	}
	close(sockfd);
	return 0;
}

客戶端:UdpClient.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
#define PORT  8888
 
struct info
{
	char buf[100];
	int port;
};
 
void *Send(void *arg)
{
	struct info SendBuf = {0};
	struct sockaddr_in server_addr;
	int ret;
 
	bzero(&server_addr, sizeof(server_addr));
	server_addr.sin_family = PF_INET;
	server_addr.sin_port = PORT;
	server_addr.sin_addr.s_addr = inet_addr("192.168.0.128");
 
	while(1)
	{
		scanf("%s %d", SendBuf.buf, &SendBuf.port);
 
		ret = sendto(*(int *)arg, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
		if (ret < 0)
		{
			perror("sendto");
			exit(1);
		}
		if (!strcmp(SendBuf.buf, "bye"))
		{
			break;
		}
		bzero(&SendBuf, sizeof(SendBuf));
	}
}
void *Recv(void *arg)
{
	struct info RecvBuf = {0};
	int length;
	struct sockaddr_in server_addr;
	int ret;
	while (1)
	{
		length = sizeof(server_addr);
		ret = recvfrom(*(int *)arg, &RecvBuf, sizeof(RecvBuf), 0, (struct sockaddr *)&server_addr, &length);
		if (ret < 0)
		{
			perror("recvfrom");
			exit(1);
		}
		printf("Recv From Server : %sn", RecvBuf.buf);
	}
}
int main()
{
	int sockfd, ret, length;
	struct info SendBuf = {0};
	pthread_t tid[2];
	sockfd = socket(PF_INET, SOCK_DGRAM, 0);
	if (-1 == sockfd)
	{
		perror("sockt");
		exit(1);
	}
	ret = pthread_create(&tid[0], NULL, Send, (void *)&sockfd);
	if (ret < 0)
	{
		perror("pthread_create");
		exit(1);
	}
	ret = pthread_create(&tid[1], NULL, Recv, (void *)&sockfd);
	if (ret < 0)
	{
		perror("pthread_create");
		exit(1);
	}
	
	pthread_join(tid[0], NULL);
	pthread_join(tid[1], NULL);
	close(sockfd);
	return 0;
}

分享到:
標簽:UDP
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定