Linux中的TCP通訊

小弟季義欽發表於2012-11-01

客戶端:

#include "apue.h"
#include <netdb.h>
#include <sys/socket.h>
#include <fcntl.h>

int main(void){
	int c_fd;
	struct sockaddr_in s_addr;	/*linux套接字地址需轉化成通用sockaddr結構地址*/
	char buf[MAXLINE] = "hello server!\n";

	/* (1) 建立套接字 */
	if((c_fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
		printf("socket error\n");

	//初始化伺服器端地址
	s_addr.sin_family = AF_INET;
	inet_pton(AF_INET,"127.0.0.1",(void *)&s_addr.sin_addr.s_addr,INET_ADDRSTRLEN);
	s_addr.sin_port = htons(5000);
	
	/* (2) 請求連線伺服器(在通訊套接字上) */
	if(connect(c_fd,(struct sockaddr *)&s_addr,sizeof(s_addr)) < 0)
		printf("connect error\n");

	/* (3) 在該套接字上傳送(接收)資料 */
	if(send(c_fd,"hello server",MAXLINE,0) < 0) 
		printf("send error\n");
	if(recv(c_fd,buf,MAXLINE,0) < 0) 
		printf("reccv error\n");
	printf("server send: %s\n",buf);

	/* (4) 關閉套接字 */
	close(c_fd);

	exit(0);
}

伺服器端:

#include "apue.h"
#include <netdb.h>
#include <sys/socket.h>

int main(void){
	int reuse = 1;
	struct sockaddr_in s_addr;/*linux套接字地址需轉化成通用sockaddr結構地址*/
	int r_fd,s_fd;
	char buf[MAXLINE];

	/* (1)建立STREAM套接字 */
	if((r_fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
		printf("socket error\n");

	/*
		注意:當客戶端正在和伺服器端通訊,此時客戶端在等待接收伺服器端訊息。
		但是伺服器卻退出了,嘗試重啟,但是根本無法重啟,而是會顯示“bind error”。
		這是由於該地址(IP+埠號)已經被繫結到一個套接字的原因。
		TCP不允許重複繫結一個地址,除非超時以後這個地址才能重新被繫結。
		---但是可以使用setsocketopt()函式設定套接字選項,使得當前與該套接字
		繫結的地址可以被重複繫結 !!!
	*/
	setsockopt(r_fd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(int));

	/* (2)繫結用於接收請求的套接字和伺服器地址 */
	s_addr.sin_family = AF_INET;
	s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	s_addr.sin_port = htons(5000);
	if(bind(r_fd,(struct sockaddr *)&s_addr,sizeof(s_addr)) < 0)
		printf("bind error\n");
	
	/* (3)宣告伺服器通訊端可以接受連線請求 */
	if(listen(r_fd,5) < 0) printf("listen error\n");

	/* (4)等待客戶連線:若accept()返回,則建立連線,返回一個新套接字(用於通訊) */
	for(;;){
		printf("waiting for ask...\n");
		fflush(stdout);
		//不關心客戶端sockaddr地址
		s_fd = accept(r_fd,NULL,NULL);

		/* (5)在該套接字上面讀寫(處理請求) */
		if(recv(s_fd,buf,MAXLINE,0) < 0)
			printf("recv error\n");
		if(send(s_fd,"OK,I have recevied your quest\n",MAXLINE,0) < 0)
			printf("send error\n");
		if(send(s_fd,"O",1,MSG_OOB) < 0)
			printf("send error\n");
		printf("client send: %s\n",buf);
	}
	/* (6)關閉新套接字和原始套接字 */
	close(r_fd);
	close(s_fd);

	exit(0);
}

相關文章