對於網絡編程,有一種說法就是一切皆socket。
之前只是大概瞭解socket網絡編程的流程,最近學習了一下如何進行socket網絡編程,實現TCP通信。
下面是服務器端的例子:
/*socket網絡編程學習
服務器端:一直監聽本機的8000端口,如果收到連接請求,將接收請求並接受客戶端發來的信息,並向客戶端返回消息。
這個程序實現的是TCP併發服務器。
併發服務器的思想是每一個客戶機的請求並不由服務器直接處理,而是由服務器創建一個子進程來處理。
2016-4-5
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAXLINE 4096
#define DEFAULT_PORT 8000
int main()
{
int socket_fd,connect_fd;
struct sockaddr_in servaddr; //用於記錄網絡地址
char buff[4096];
int n;
//初始化
memset(&servaddr ,0 ,sizeof(servaddr)); //結構體置零
servaddr.sin_family=AF_INET; //AF_INET表示IP協議族
servaddr.sin_addr.s_addr=htonl(INADDR_ANY); //IP地址設置爲INADDR_ANY,讓系統自動獲取本機的IP地址。
servaddr.sin_port = htons(DEFAULT_PORT); //設置的端口爲DEFAULT_PORT
//初始化socket
if((socket_fd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
printf("create socket error : %s(error: %d)\n",strerror(errno),errno);
exit(0);
}
//將本地地址和端口號綁定到所創建的套接字上
if(bind(socket_fd,(struct sockaddr*)&servaddr,sizeof(servaddr))==-1) //可以將sockaddr換爲sockaddr_in,編譯會有警告
{
printf("bind socket error:%s(error:%d)\n",strerror(errno),errno);
exit(0);
}
//開始監聽是否有客戶端連接,,,,並設置允許的最大連接數
if(listen(socket_fd,10)==-1)
{
printf("listen socket error:%s(errno:%d)\n",strerror(errno),errno);
exit(0);
}
printf("=====waiting for client's request ======\n");
while(1)
{
//阻塞直到有客戶端連接,不然多浪費CPU資源。
if((connect_fd=accept(socket_fd,(struct sockaddr*)NULL,NULL)) == -1) //accept函數用來等待來自客戶端的socket的連接請求
{
printf("accept socket error :%s(errno:%d)\n",strerror(errno),errno);
continue;
}
//接收客戶端傳過來的數據
n=recv(connect_fd,buff,MAXLINE,0);
//向客戶端發送迴應數據
if(!fork())
{
if(send(connect_fd,"\tHello,your message has been received!\n",40,0)==-1)
perror("send error");
close(connect_fd);
exit(0); //關掉髮送進程
}
buff[n]='\0';
printf("recv msg from client:\n\t%s",buff);
close(connect_fd);
}
close(socket_fd);
}
接着是客戶端的代碼:
/*socket網絡編程學習 基於TCP網絡程序設計
客戶端:向相應的IP地址主機的8000端口發送數據,並接收回執。
2016-4-5
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define DEFAULT_PORT 8000
#define MAXLINE 4096
int main(int argc,char **argv)
{
int sockfd,n,rec_len;
char recvline[4096],sendline[4096];
char buf[MAXLINE];
struct sockaddr_in servaddr;
if(argc != 2)
{
printf("please input: ./client <ipaddress>\n");
exit(0);
}
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(DEFAULT_PORT);
if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr)<=0) //inet_pton是Linux下IP地址轉換函數,可以將IP地址在“點分十進制”和整數之間轉換。
{
printf("IP error:%s(errno:%d)\n",strerror(errno),errno);
exit(0);
}
if((sockfd =socket(AF_INET,SOCK_STREAM,0))<0) //創建一個socket
{
printf("create socket error :%s(errno:%d)\n",strerror(errno),errno);
exit(0);
}
if(connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0) //連接服務器
{
printf("connect error :%s(errno:%d)\n",strerror(errno),errno);
exit(0);
}
printf("send msg to server:\n");
fgets(sendline,4096,stdin);
if( send(sockfd,sendline,strlen(sendline),0)<0) //發送數據
{
printf("send msg error :%s(errno:%d)\n",strerror(errno),errno);
exit(0);
}
if((rec_len=recv(sockfd,buf,MAXLINE,0))==-1) //接收回執
{
perror("recv error");
exit(1);
}
buf[rec_len]='\0';
printf("send success:%s",buf); //打印回執
close(sockfd);
exit(0);
}
將兩個程序進行編譯運行。
接着運行着兩個程序:
客戶端發送CSDN給服務器,並接收來自服務器的回執。
服務器端收到來自客戶端發送的數據。
內容多參考:http://blog.csdn.net/hguisu/article/details/7445768/