socket編程與利用進程進行多并行連接
呈現一張基本的socket阻塞式模型,如下圖:
一: 對于一對一的進行C/S回射:
服務端(server.c):
#include<unistd.h>include<stdio.h>
include<string.h>
include<stdlib.h>
include<netinet/in.h>
include<sys/socket.h>
include<sys/types.h>
include<error.h>
define ERR_EXIT(m) \
do{ \ perror(m); \ exit(1); \ }while(0)
int main (void) { int sock, conn; if ((sock = socket (PF_INET, SOCK_STREAM, 0)) < 0) ERR_EXIT ("socket"); struct sockaddr_in sockaddr; memset (&sockaddr, 0, sizeof (sockaddr)); sockaddr.sin_family = AF_INET; sockaddr.sin_port = htons (5528); sockaddr.sin_addr.s_addr = htonl (INADDR_ANY); if (bind (sock, (struct sockaddr ) &sockaddr, sizeof (sockaddr)) < 0) ERR_EXIT ("Bind"); if (listen (sock, SOMAXCONN) < 0) ERR_EXIT ("Listen"); struct sockaddr_in client; memset (&client, 0, sizeof (client)); socklen_t addrlen = sizeof (client); if ((conn = accept (sock, (struct sockaddr ) &client, &addrlen)) < 0) ERR_EXIT ("Accept"); char sed[1024], recv[1024]; while (fgets (sed, sizeof (sed), stdin) != NULL || 1 == 1) { if (strlen (sed) > 0) write (conn, sed, sizeof (sed)); if (read (conn, recv, sizeof (recv)) > 0) { fputs (recv, stdout); if (strcmp (recv, "exit") == 0) break; write (conn, recv, sizeof (recv)); } else ERR_EXIT ("read..."); } close (conn); close (sock); return 0; }</pre>
客戶端(client.c):#include<unistd.h>include<stdio.h>
include<string.h>
include<error.h>
include<netinet/in.h>
include<stdlib.h>
include<sys/socket.h>
include<sys/types.h>
define ERR_EXIT( m ) \
do{ \ perror(m); \ exit(1); \ }while(0);
int main (void) { int socketid, conn;
if ((socketid = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) ERR_EXIT ("socket");
struct sockaddr_in server_addr; memset (&server_addr, 0, sizeof (server_addr));
server_addr.sin_family = AF_INET; server_addr.sin_port = htons (5528); server_addr.sin_addr.s_addr = inet_addr ("127.0.0.1"); if ((conn = connect (socketid, (struct sockaddr *) &server_addr, sizeof (server_addr))) < 0) ERR_EXIT ("connect"); char sendbuf[1024], recivebuf[1024]; while (fgets (sendbuf, sizeof (sendbuf), stdin) != NULL) { write (socketid, sendbuf, sizeof (sendbuf)); read (socketid, recivebuf, sizeof (recivebuf)); fputs (recivebuf, stdout); if (strcmp (recivebuf, "exit") == 0) { ERR_EXIT ("exit"); break; } } close (conn); close (socketid); return 0; }</pre>
相關的makefile文件
makefile文件:.SUFFIXES: .o.c .PHONY: clean .PHONY: start
CC =gcc SRC =server.c OBJS =$(SRC:.c =.o) BIN = Server
start: $(CC) -o $(BIN) $(OBJS)
.o.c: $(CC) -g -Wall $@ -c $< clean: rm -f $(OBJS)</pre>
但是上述雖然滿足了基本的socket套路,但是當我們關閉服務可執行程序時,在開啟就會出現地址被占用,解決此等問題,需再加上一個setsockopt()函數,對齊進行設定。
詳細可以去查詢man幫助(man setsockopt)
代碼:
int on = 1; if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) { ERR_EXIT ("setsockopt"); }if (bind (sock, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) < 0) ERR_EXIT ("Bind");</pre>
二: 利用進程進行并行socket阻塞式連接:客戶端和makefile文件和上面一樣,只是將socket的服務端,修改為調用進程來進行多并發連接即可!
服務端(server.c):
#include<unistd.h>include<stdio.h>
include<string.h>
include<stdlib.h>
include<netinet/in.h>
include<sys/socket.h>
include<sys/types.h>
include<error.h>
define ERR_EXIT(m) \
do{ \ perror(m); \ exit(1); \ }while(0)
void print (int conn){
char sed[1024], recv[1024]; while (fgets (sed, sizeof (sed), stdin) != NULL || 1 == 1) { if (strlen (sed) > 0) write (conn, sed, sizeof (sed)); if (read (conn, recv, sizeof (recv)) > 0) { fputs (recv, stdout); if (strcmp (recv, "exit") == 0) break; write (conn, recv, sizeof (recv)); } else ERR_EXIT ("read..."); } close (conn); }
int main (void) { int sock, conn; if ((sock = socket (PF_INET, SOCK_STREAM, 0)) < 0) ERR_EXIT ("socket"); struct sockaddr_in sockaddr; memset (&sockaddr, 0, sizeof (sockaddr)); sockaddr.sin_family = AF_INET; sockaddr.sin_port = htons (5528); sockaddr.sin_addr.s_addr = htonl (INADDR_ANY);
int on = 1; if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) { ERR_EXIT ("setsockopt"); }
if (bind (sock, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) < 0) ERR_EXIT ("Bind");
if (listen (sock, SOMAXCONN) < 0) ERR_EXIT ("Listen");
struct sockaddr_in client; memset (&client, 0, sizeof (client)); socklen_t addrlen = sizeof (client); pid_t pid ;
while (1) { if((conn = accept (sock, (struct sockaddr *) &client, &addrlen)) < 0) ERR_EXIT ("Accept"); pid = fork (); if (pid == -1) ERR_EXIT ("fork"); else if (pid == 0){ close (sock); print (conn); } else close (conn); } close (sock); return 0; }</pre>
編程是一種快樂,享受代碼帶給我的樂趣!!!來自:http://www.cnblogs.com/gongxijun/p/4592864.html