zoukankan      html  css  js  c++  java
  • C语言写了一个socket server端,适合windows和linux,用GCC编译运行通过

    ///////////////////////////////////////////////////////////////////////////////
    /*
    gcc -Wall -o s1 s1.c -lws2_32
    */
    ///////////////////////////////////////////////////////////////////////////////

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>

    #define _WIN32_WINNT 0x501
    #define PORT 4000
    #define IP_ADDRESS "127.0.0.1"
    ///////////////////////////////////////////////////////////////////////////////
    // SK

    #ifdef _WIN32_WINNT
    #include <ws2tcpip.h>
    #include <winsock2.h>
    WSADATA Ws;
    #else
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <sys/un.h>
    #include <netdb.h>
    #endif

    ///////////////////////////////////////////////////////////////////////////////
    // SK

    void connect_inet_socket( int *psockfd, const char* host, int port );

    #ifdef _WIN32_WINNT
    void connect_windows_socket( int *psockfd, const char* pathname );
    #else
    void connect_unix_socket( int *psockfd, const char* pathname );
    #endif

    void writebuffer_socket( int sockfd, const void *data, int len );
    void readbuffer_socket( int sockfd, void *data, int len );
    void shutdown_socket( int sockfd );

    ///////////////////////////////////////////////////////////////////////////////
    // SK
    /* Access to sockets needs to be done with a wrapper function 'connect_socket'
    and it is substituted by 'connect_windows_socket' or by 'connect_unix_socket'
    ( depends on a state of the macro _WIN32 ) during preprocessing phase of
    the compilation.
    For portability 'connect_windows_socket' and 'connect_unix_socket' shouldn't
    be used directly and the wrapper function 'connect_socket' must be used instead.
    */

    #ifdef _WIN32_WINNT
    #define connect_socket connect_windows_socket
    #else
    #define connect_socket connect_unix_socket
    #endif

    int socket_desc;
    struct sockaddr_in server;

    ///////////////////////////////////////////////////////////////////////////////
    /* Opens an internet socket.

    Note that fortran passes an extra argument for the string length,
    but this is ignored here for C compatibility.

    Args:
    psockfd: The id of the socket that will be created.
    port: The port number for the socket to be created. Low numbers are
    often reserved for important channels, so use of numbers of 4
    or more digits is recommended.
    host: The name of the host server.
    */

    void connect_inet_socket( int *psockfd, const char* host, int port )
    {
    int sockfd, ai_err;

    // creates an internet socket

    // fetches information on the host
    struct addrinfo hints, *res;
    char service[256];

    memset(&hints, 0, sizeof(hints));
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_family = AF_UNSPEC;
    hints.ai_flags = AI_PASSIVE;

    //sprintf(service, "%d", port); // convert the port number to a string
    //ai_err = getaddrinfo(host, service, &hints, &res);
    //if (ai_err!=0) {
    // printf("Error code: %i ",ai_err);
    // perror("Error fetching host data. Wrong host name?");
    // exit(-1);
    //}

    // creates socket
    //sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    sockfd = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
    if (sockfd < 0) {
    perror("Error opening socket");
    exit(-1);
    }
    else
    {
    printf("creates socket:%d ", sockfd);
    }

    // makes connection
    if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0) {
    perror("Error opening INET socket: wrong port or server unreachable");
    exit(-1);
    }
    freeaddrinfo(res);

    *psockfd = sockfd;
    }

    ///////////////////////////////////////////////////////////////////////////////
    // SK
    /* Opens a socket.

    Note that fortran passes an extra argument for the string length,
    but this is ignored here for C compatibility.

    Args:
    psockfd: The id of the socket that will be created.
    pathname: The name of the file to use for sun_path.
    */

    #ifdef _WIN32_WINNT

    void connect_windows_socket( int *psockfd, const char* pathname )
    {
    // Required functionality for Windows

    // ...
    }

    #else

    void connect_unix_socket( int *psockfd, const char* pathname )
    {
    // Required functionality for Unix

    int sockfd, ai_err;

    struct sockaddr_in serv_addr;

    printf("Connecting to :%s: ",pathname);

    // fills up details of the socket addres
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sun_family = AF_UNIX;
    /* Beware of buffer over runs
    UNIX Network Programming by Richard Stevens mentions
    that the use of sizeof() is ok, but see
    http://mail-index.netbsd.org/tech-net/2006/10/11/0008.html
    */
    if ((int)strlen(pathname)> sizeof(serv_addr.sun_path)) {
    perror("Error opening UNIX socket: pathname too long ");
    exit(-1);
    } else {
    strcpy(serv_addr.sun_path, pathname);
    }
    // creates a unix socket

    // creates the socket
    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

    // connects
    if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
    perror("Error opening UNIX socket: path unavailable, or already existing");
    exit(-1);
    }
    *psockfd = sockfd;
    }

    #endif

    ///////////////////////////////////////////////////////////////////////////////
    /* Writes to a socket.

    Args:
    sockfd: The id of the socket that will be written to.
    data: The data to be written to the socket.
    len: The length of the data in bytes.
    */

    void writebuffer_socket( int sockfd, const void *data, int len )
    {
    int n;

    n = write(sockfd, (char *) data, len);
    if (n < 0) {
    perror("Error writing to socket: server has quit or connection broke");
    exit(-1);
    }
    }

    ///////////////////////////////////////////////////////////////////////////////
    /* Reads from a socket.

    Args:
    sockfd: The id of the socket that will be read from.
    data: The storage array for data read from the socket.
    len: The length of the data in bytes.
    */

    void readbuffer_socket( int sockfd, void *data, int len )
    {
    int n, nr;
    char *pdata;

    pdata = (char *) data;
    n = nr = read(sockfd, pdata, len);

    while (nr > 0 && n < len) {
    nr = read(sockfd, &(pdata[n]), len - n);
    n += nr;
    }
    if (n == 0) {
    perror("Error reading from socket: server has quit or connection broke");
    exit(-1);
    }
    }

    ///////////////////////////////////////////////////////////////////////////////
    /* Shuts down the socket.
    */

    void shutdown_socket( int sockfd )
    {
    shutdown( sockfd, 2 );
    close( sockfd );
    }

    DWORD WINAPI ClientThread(LPVOID lpParameter)
    {
    SOCKET CientSocket = (SOCKET)lpParameter;
    int Ret = 0;
    char RecvBuffer[1024];
    char message[] = "Hello Master HaKu!";

    while ( 1 )
    {
    memset(RecvBuffer, 0x00, sizeof(RecvBuffer));
    Ret = recv(CientSocket, RecvBuffer, 1024, 0);
    if ( Ret == 0 || Ret == SOCKET_ERROR )
    {
    printf("客户端退出! ");
    break;
    }
    printf("接收到客户信息为%s ", RecvBuffer);
    //Ret = send(CientSocket, "hello world", (int)strlen("hello world"), 0);
    //Ret = write(CientSocket, "hello world", sizeof("hello world"));
    //write(CientSocket, message, sizeof(message));
    send(CientSocket, "hello world", strlen("hello world"), 0);
    //if ( Ret == 0 || Ret == SOCKET_ERROR )
    //{
    printf("返回给客户端%s ", message);
    // break;
    //}
    }

    return 0;
    }


    int main(void)
    {
    int *socket_desc;
    SOCKET ServerSocket, ClientSocket;
    struct sockaddr_in LocalAddr, ClientAddr;
    int Ret = 0;
    int AddrLen = 0;
    HANDLE hThread = NULL;
    char SendBuffer[MAX_PATH];
    char message[30] = "Hello Master HaKu!";

    #ifdef _WIN32_WINNT
    //Init Windows Socket
    if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )
    {
    printf("Init Windows Socket Failed");
    return -1;
    }
    #endif

    //connect_inet_socket(socket_desc, "http://blog.csdn.net", 80);
    //Create socket
    ServerSocket = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
    if (socket_desc == -1)
    {
    printf("Could not create socket");
    }

    LocalAddr.sin_family = AF_INET;
    LocalAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
    LocalAddr.sin_port = htons(PORT);
    memset(LocalAddr.sin_zero, 0x00, 8);

    //Bind Socket
    Ret = bind(ServerSocket, (struct sockaddr*)&LocalAddr, sizeof(LocalAddr));
    if ( Ret != 0 )
    {
    printf("Bind Socket Failed");
    //return -1;
    }
    //listen

    Ret = listen(ServerSocket, 10);
    if ( Ret != 0 )
    {
    printf("listen Socket Failed");
    //return -1;
    }

    printf("服务端已经启动 ");

    while ( 1 )
    {
    AddrLen = sizeof(ClientAddr);
    ClientSocket = accept(ServerSocket, (struct sockaddr*)&ClientAddr, &AddrLen);
    if ( ClientSocket == INVALID_SOCKET )
    {
    printf("Accept Failed");
    break;
    }

    //write(ClientSocket, message, sizeof(message));
    send(ClientSocket, message, strlen(message), 0);

    printf("客户端连接 ");

    hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)ClientSocket, 0, NULL);
    if ( hThread == NULL )
    {
    printf("Create Thread Failed!");
    break;
    }

    CloseHandle(hThread);
    }

    closesocket(ServerSocket);
    closesocket(ClientSocket);
    WSACleanup();

    return 0;
    }

  • 相关阅读:
    android 中文 api (43) —— Chronometer
    SVN客户端清除密码
    Android 中文 API (35) —— ImageSwitcher
    Android 中文API (46) —— SimpleAdapter
    Android 中文 API (28) —— CheckedTextView
    Android 中文 API (36) —— Toast
    Android 中文 API (29) —— CompoundButton
    android 中文 API (41) —— RatingBar.OnRatingBarChangeListener
    Android 中文 API (30) —— CompoundButton.OnCheckedChangeListener
    Android 中文 API (24) —— MultiAutoCompleteTextView.CommaTokenizer
  • 原文地址:https://www.cnblogs.com/bdccloudy/p/7678063.html
Copyright © 2011-2022 走看看