標籤:
一、linux下TCP網路編程基礎,需要瞭解相關函數
Socket():用於通訊端初始化。
Bind():將 socket 與本機上的一個連接埠綁定,就可以在該連接埠監聽服務要求。
Listen():使socket處於被動的監聽模式,並為該 socket 建立一個輸入
資料隊列,將到達的伺服器, 請求儲存在此隊列中,直到程式處理他們。
Accept():讓伺服器接收客戶的串連請求。
Connect():用戶端使用connect函數來配置 socket並與遠端伺服器建立一個 TCP 串連。
Close():關閉socket
Send():發送函數
Recv():接受函數
二、伺服器和用戶端流程圖如所示
三、linux下TCP編程執行個體
TCP伺服器程式
/* server.c */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define PORT 2000 //定義連接埠號碼
#define BUFFER_SIZE 1024
#define MAX_QUE_CONN_NM 5 //最大緩衝隊列
int main(void)
{
/*下面該乙太網路通訊端地址結構體非常重要*/
struct sockaddr_in server_addr,client_addr;
int sin_size,recvbytes,wbytes;
int ser_fd,cli_fd;
char buf[BUFFER_SIZE];
/* 建立 socket 串連,IPv4 協議,位元組流通訊端 */
if((ser_fd = socket(AF_INET,SOCK_STREAM,0))== -1)
{
perror("socket");
exit(1);
}
printf("Socket id = %d\n",ser_fd);
/* 初始化 sockaddr_in 結構體 */
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),8);
/* 綁定函數 bind */
if(bind(ser_fd,(struct sockaddr *)&server_addr,sizeof(struct
sockaddr))==-1)
{
perror("bind");
exit(1);
}
printf("Bind success!\n");
/* 調用 listen 函數,進行監聽 */
if(listen(ser_fd,MAX_QUE_CONN_NM)== - 1)
{
perror("listen");
exit(1);
}
printf("Listening......\n");
/* 調用 accept 函數,等待用戶端的串連 */
if((cli_fd = accept(ser_fd,(struct sockaddr *)&client_addr,&sin_size))==-1)
{
perror("accept");
exit(1);
}
printf("Have client ready for connecting\n");
/* 調用 recv 函數接收用戶端的請求 */
memset(buf,0,sizeof(buf));
if((recvbytes = recv(cli_fd,buf,BUFFER_SIZE,0))== -1)
{
perror("recv");
exit(1);
}
/* 將收到的資訊(客服端發來的資訊)列印出來 */
printf("Received a message:%s\n",buf);
/*對用戶端發過來的資料進行處理,只是將首字元加2,再發給用戶端*/
buf[0]=buf[0]+2;
if( ( wbytes = write(cli_fd,buf,strlen(buf)) ) == -1 )
{
perror("handle send");
exit(1);
}
else
printf("handle buf is %s\n",buf);
/* 關閉 socket */
close(ser_fd);
return 0;
}
TCP用戶端程式
/*client*/
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/ioctl.h>
#include<netinet/in.h>
#include<netdb.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#define PORT 2000 //連接埠號碼
#define BUFFER_SIZE 1024
int main(int argc,char *argv[])
{
struct sockaddr_in server_addr;
int sockfd,sendbytes,rbytes;
//int ser_fd;
char buf[BUFFER_SIZE];
struct hostent *host;
/*指定輸入參數為3個,否則出錯*/
if(argc!=3)
{
perror("Usage:./clinet IP address Text\n");
exit(1);
}
/*位址解析函數*/
if( ( host = gethostbyname(argv[1]) ) == NULL ) //得到主機名稱及相應資訊
{
perror("gethostbyname");
exit(1);
}
memset(buf,0,sizeof(buf));
sprintf(buf,"%s",argv[2]);
buf[strlen(buf)+1]=‘\0‘;
/*建立socket串連,IPv4協議,位元組流通訊端*/
if( ( sockfd = socket(AF_INET,SOCK_STREAM,0) ) == -1 )
{
perror("socket");
exit(1);
}
printf("Socket id = %d\n",sockfd);
/*初始化sockaddr_in 結構體*/
server_addr.sin_family = AF_INET; //TCP/IP協議簇
server_addr.sin_port = htons(PORT); // sin_port儲存連接埠號碼(使用網路位元組順序) htons將unsigned short從主機位元組序轉化為網路位元組序
server_addr.sin_addr = *((struct in_addr *)host->h_addr); //前面指過的,host主機名稱及相應資訊的指標,這裡為IP地址
bzero(&(server_addr.sin_zero),8); //等同於memset,清空作用
/*調用connect函數主動發起對伺服器的串連*/
if( ( connect(sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr)) ) == -1 ) //第2個參數,指向要串連通訊端的sockaddr結構體的指標
{
perror("connect");
exit(1);
}
printf("connect server success!\n");
/*發送訊息給伺服器端*/
if( ( sendbytes = send(sockfd,buf,strlen(buf),0) ) == -1 )
{
perror("send");
exit(1);
}
else printf("buf is %s\n",buf);
/* 將伺服器處理後的資料讀取出來 */
if ((rbytes=read(sockfd,buf,100))==-1)
{
printf("read handle error\n");
exit(0);
}
else
printf("read handle buf is %s \n",buf);
close(sockfd);
return 0;
}
四、程式運行結果如下:
用戶端結果
伺服器結果
五、C#socket()編程
參考資料:http://lanxicy.com/read/9740d8d480de02ad528ada5d.html
對該資料進行了些修改產生exe檔案
運行結果如下
C#TCP用戶端
C#TCP伺服器
六、由於linux下和C#下都使用了TCP網路編程,所以用linux當作用戶端,C#當作伺服器,設定好連接埠號碼和IP地址,
他們之間是可以通訊的,然後在C#下可以把相關的資料寫入資料庫裡面,相關網頁再從資料庫裡面讀取相關資料就行了。
運行結果如下
Linux用戶端
C#伺服器
七、總結心得
linux下的網路編程和Windows下C#網路編程都是使用TCP協議進行通訊,所以即使是跨平台,他們之間還是能進行通訊的。
說明一下:轉載請註明出處!
Linux下TCP網路編程與基於Windows下C#socket編程之間通訊